#ifndef	_LLC_ENCAP_UTIL_C_
#define	_LLC_ENCAP_UTIL_C_
/*****************************************************************************
 *                            Intel Proprietary
 *
 * Copyright (c) 1998-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, CA  95052-8119
 *****************************************************************************/

/**
 *****************************************************************************
 * @ingroup LlcEncap
 * File:  llc_encap_util.c 
 * @description
 *    This file contains the utility functions for LLCSNAP header encapsulation
 *
 *    Change History:
 *    02/March/2003    Created    Shreekanth Patel
 *****************************************************************************/

/*****************************************************************************
 *
 * Contents:
 *        Definitions of following local functions:
 *            LlcEncap_ReadNextHopEntry()
 *            LlcEncap_AddLlcToPayload()
 *	          LlcEncap_UpdateMetaData
 *            LlcEncap_ComputePacketCellCount       
 *
 *****************************************************************************/

#include "ixp.h"
#include "ixp_lib.h"
#include "ixp_buf.c"

#include "dl_meta.h"
#include "dl_system.h"
#include "dl_pkt_proc.h"
#include "dl_meta.c"
#include "llc_encap.h"

extern volatile __declspec(gp_reg) hdr_cache_handle_t dlHdrHandle;
extern dl_buf_handle_t 	dlBufHandle;

/*****************************************************************************
 * Abstract:
 *    Reads the LLCSNAP table entry for the packet using nextHopId as an index.
 *
 * Assumptions:
 *    It assumes that the L2 table is in SRAM.
 *****************************************************************************/
__forceinline extern void
LlcEncap_ReadNextHopEntry (
						   __declspec (sram_read_reg) llc_table_entry_t* llcSnapEntry
						  )
{
	__declspec (sram) llc_table_entry_t* __declspec(gp_reg) llcSnapEntryAddr;
	SIGNAL next_hop_entry_rd_sig;

	/* 
	 * Calculate the address of the entry in SRAM from the nextHopId in meta data.
	 */
	llcSnapEntryAddr = (llc_table_entry_t*) L2_TABLE_SRAM_BASE + dlMeta.nextHopId;

	/*
	 * Read the next hop entry in SRAM
	 */
	sram_read (llcSnapEntry, (volatile __declspec(sram) llc_table_entry_t*) llcSnapEntryAddr,
				4, sig_done, &next_hop_entry_rd_sig);

	/*
	 * Wait for sram read completion 
	 */
	wait_for_all(&next_hop_entry_rd_sig);

	return;
}

/*****************************************************************************
 * Abstract:
 *    Encapsulates LLC/SNAP header to the IP packet.
 *
 * Assumptions:
 *****************************************************************************/
__forceinline extern void 
LlcEncap_AddLlcToPayload (
						  __declspec(local_mem, aligned(32)) unsigned int * p_pkt,
						  __declspec(sram_read_reg) llc_table_entry_t *llc_snap_entry
						 )
{

	*(p_pkt + 2) = llc_snap_entry->llc_hdr.llcSnapHdr0;
	*(p_pkt + 3) = llc_snap_entry->llc_hdr.llcSnapHdr1;

	LlcEncap_UpdateMetaData ();
}

/***************************************************************************** 
 * Abstract:
 *    Updates Meta data variables after adding LLC/SNAP after adding LLCSNAP
 *    header to IP packet.
 *
 * Assumptions:
 *****************************************************************************/
void 
LlcEncap_UpdateMetaData (void)
{
	/*
	 * Update sop buffer size, packet size & payload offset
	 */
	dlMeta.bufferSize = dlMeta.bufferSize + LLC_SNAP_SIZE;

	dlMeta.packetSize = dlMeta.packetSize + LLC_SNAP_SIZE;

	dlMeta.offset = dlMeta.offset - LLC_SNAP_SIZE;

	dlHdrHandle.hdrOffset = dlHdrHandle.hdrOffset - (LLC_SNAP_SIZE/sizeof (uint32_t));
}

/*****************************************************************************
 * Abstract:
 *    Computes number of 48-byte cells in the packet.
 *    Parameters:
 *        Outputs:
 *        out_packet_cell_count :
 *            Number of 48-byte cells in the packet.
 *        Inputs:
 *        addn_cell:
 *            When set to 'ADDN_CELL' the macro computes cell count
 *            taking into consideration the need for an additional
 *            cell for the packet if the payload of the last cell
 *            of the packet is >40. The additional cell is needed
 *            in this case to store the 8-byte CPCS trailer.
 *
 *     Example :
 *                packet size  addn_cell      packet cell count
 *                (bytes)
 *                 40           --          1
 *                 47           --          1
 *                 48           --          1
 *                 49           --          2
 *                 40           ADDN_CELL   1
 *                 47           ADDN_CELL   2
 *                 48           ADDN_CELL   2
 *                 49           ADDN_CELL   2
 *
 * Assumptions:
 *****************************************************************************/
unsigned int
LlcEncap_ComputePacketCellCount (
							     unsigned int addn_cell
								)
{

	__declspec (gp_reg) unsigned int p, c, out_packet_cell_count;
	
	/* 
	 * Check if packet size is 48 or 56 bytes
	 */
	/* p = dlMeta.packetSize + ((addn_cell == ADDN_CELL)?56:48); */
	if (addn_cell == ADDN_CELL)
	{
		p = dlMeta.packetSize + 56;
	} else
	{
		p = dlMeta.packetSize + 48;
	}
	
	/*
	 * Compute cell count
	 */
	c = ((((p << 2) + p) << 2) + p);
	
	c = (c + (c << 6));
	
	out_packet_cell_count = ((c >> 16) + ((((c & 0xffff) << 12) + c) >> 28));

	return out_packet_cell_count;
}

#endif	/* _LLC_ENCAP_UTIL_C_ */