text: #include "headers.h"
  
  static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,B_UINT16  uiClsId,S_SERVICEFLOW_TABLE *psServiceFlowTable,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI);
  
  static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,B_UINT16  uiClsId,S_SERVICEFLOW_ENTRY *pstServiceFlowEntry,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI);
  
  static UINT CreateClassifierPHSRule(B_UINT16  uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI);
  
  static UINT UpdateClassifierPHSRule(B_UINT16  uiClsId,S_CLASSIFIER_ENTRY *pstClassifierEntry,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI);
  
  static BOOLEAN ValidatePHSRuleComplete(S_PHS_RULE *psPhsRule);
  
  static BOOLEAN DerefPhsRule(B_UINT16  uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule);
  
  static UINT GetClassifierEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiClsid,E_CLASSIFIER_ENTRY_CONTEXT eClsContext, S_CLASSIFIER_ENTRY **ppstClassifierEntry);
  
  static UINT GetPhsRuleEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,S_PHS_RULE **ppstPhsRule);
  
  static void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable);
  
  static int phs_compress(S_PHS_RULE   *phs_members,unsigned char *in_buf,
  						unsigned char *out_buf,unsigned int *header_size,UINT *new_header_size );
  
  
  static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer,
  								unsigned char *phsf,unsigned char *phsm,unsigned int phss,unsigned int phsv,UINT *new_header_size );
  
  static int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,\
  						  S_PHS_RULE   *phs_rules,UINT *header_size);
  
  
  static ULONG PhsCompress(void* pvContext,
  				  B_UINT16 uiVcid,
  				  B_UINT16 uiClsId,
  				  void *pvInputBuffer,
  				  void *pvOutputBuffer,
  				  UINT *pOldHeaderSize,
  				  UINT *pNewHeaderSize );
  
  static ULONG PhsDeCompress(void* pvContext,
  				  B_UINT16 uiVcid,
  				  void *pvInputBuffer,
  				  void *pvOutputBuffer,
  				  UINT *pInHeaderSize,
  				  UINT *pOutHeaderSize);
  
  
  
  #define IN
  #define OUT
  
  /*
  Function:				PHSTransmit
  
  Description:			This routine handle PHS(Payload Header Suppression for Tx path.
  					It extracts a fragment of the NDIS_PACKET containing the header
  					to be suppressed.It then supresses the header by invoking PHS exported compress routine.
  					The header data after supression is copied back to the NDIS_PACKET.
  
  
  Input parameters:		IN PMINI_ADAPTER Adapter         - Miniport Adapter Context
  						IN Packet 				- NDIS packet containing data to be transmitted
  						IN USHORT Vcid        - vcid pertaining to connection on which the packet is being sent.Used to
  										        identify PHS rule to be applied.
  						B_UINT16 uiClassifierRuleID - Classifier Rule ID
  						BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF.
  
  Return:					STATUS_SUCCESS - If the send was successful.
  						Other          - If an error occured.
  */
  
  int PHSTransmit(PMINI_ADAPTER Adapter,
  					 struct sk_buff	**pPacket,
  					 USHORT Vcid,
  					 B_UINT16 uiClassifierRuleID,
  					 BOOLEAN bHeaderSuppressionEnabled,
  					 UINT *PacketLen,
  					 UCHAR bEthCSSupport)
  {
  
  	//PHS Sepcific
  	UINT    unPHSPktHdrBytesCopied = 0;
  	UINT	unPhsOldHdrSize = 0;
  	UINT	unPHSNewPktHeaderLen = 0;
  	/* Pointer to PHS IN Hdr Buffer */
  	PUCHAR pucPHSPktHdrInBuf =
  				Adapter->stPhsTxContextInfo.ucaHdrSupressionInBuf;
  	/* Pointer to PHS OUT Hdr Buffer */
  	PUCHAR  pucPHSPktHdrOutBuf =
  					Adapter->stPhsTxContextInfo.ucaHdrSupressionOutBuf;
  	UINT       usPacketType;
  	UINT       BytesToRemove=0;
  	BOOLEAN  bPHSI = 0;
  	LONG ulPhsStatus = 0;
  	UINT 	numBytesCompressed = 0;
  	struct sk_buff *newPacket = NULL;
  	struct sk_buff *Packet = *pPacket;
  
  	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "In PHSTransmit");
  
  	if(!bEthCSSupport)
  		BytesToRemove=ETH_HLEN;
  	/*
  		Accumulate the header upto the size we support supression
  		from NDIS packet
  	*/
  
  	usPacketType=((struct ethhdr *)(Packet->data))->h_proto;
  
  
  	pucPHSPktHdrInBuf = Packet->data + BytesToRemove;
  	//considering data after ethernet header
  	if((*PacketLen - BytesToRemove) < MAX_PHS_LENGTHS)
  	{
  
  		unPHSPktHdrBytesCopied = (*PacketLen - BytesToRemove);
  	}
  	else
  	{
  		unPHSPktHdrBytesCopied = MAX_PHS_LENGTHS;
  	}
  
  	if( (unPHSPktHdrBytesCopied > 0 ) &&
  		(unPHSPktHdrBytesCopied <= MAX_PHS_LENGTHS))
  	{
  
  
  		// Step 2 Supress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf.
  	// Suppress only if IP Header and PHS Enabled For the Service Flow
  		if(((usPacketType == ETHERNET_FRAMETYPE_IPV4) ||
  			(usPacketType == ETHERNET_FRAMETYPE_IPV6)) &&
  			(bHeaderSuppressionEnabled))
  		{
  				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nTrying to PHS Compress Using Classifier rule 0x%X",uiClassifierRuleID);
  
  
  				unPHSNewPktHeaderLen = unPHSPktHdrBytesCopied;
  				ulPhsStatus = PhsCompress(&Adapter->stBCMPhsContext,
  					Vcid,
  					uiClassifierRuleID,
  					pucPHSPktHdrInBuf,
  					pucPHSPktHdrOutBuf,
  					&unPhsOldHdrSize,
  					&unPHSNewPktHeaderLen);
  				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nPHS Old header Size : %d New Header Size  %d\n",unPhsOldHdrSize,unPHSNewPktHeaderLen);
  
  				if(unPHSNewPktHeaderLen == unPhsOldHdrSize)
  				{
  					if(  ulPhsStatus == STATUS_PHS_COMPRESSED)
  							bPHSI = *pucPHSPktHdrOutBuf;
  					ulPhsStatus = STATUS_PHS_NOCOMPRESSION;
  				}
  
  				if(  ulPhsStatus == STATUS_PHS_COMPRESSED)
  				{
  					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHS Sending packet Compressed");
  
  					if(skb_cloned(Packet))
  					{
  						newPacket = skb_copy(Packet, GFP_ATOMIC);
  
  						if(newPacket == NULL)
  							return STATUS_FAILURE;
  
  						dev_kfree_skb(Packet);
  						*pPacket = Packet = newPacket;
  						pucPHSPktHdrInBuf = Packet->data  + BytesToRemove;
  					}
  
  					numBytesCompressed = unPhsOldHdrSize - (unPHSNewPktHeaderLen+PHSI_LEN);
  
  					memcpy(pucPHSPktHdrInBuf + numBytesCompressed, pucPHSPktHdrOutBuf, unPHSNewPktHeaderLen + PHSI_LEN);
  					memcpy(Packet->data + numBytesCompressed, Packet->data, BytesToRemove);
  					skb_pull(Packet, numBytesCompressed);
  
  					return STATUS_SUCCESS;
  				}
  
  				else
  				{
  					//if one byte headroom is not available, increase it through skb_cow
  					if(!(skb_headroom(Packet) > 0))
  					{
  						if(skb_cow(Packet, 1))
  						{
  							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "SKB Cow Failed\n");
  							return STATUS_FAILURE;
  						}
  					}
  					skb_push(Packet, 1);
  
  					// CAUTION: The MAC Header is getting corrupted here for IP CS - can be saved by copying 14 Bytes.  not needed .... hence corrupting it.
  					*(Packet->data + BytesToRemove) = bPHSI;
  					return STATUS_SUCCESS;
  			}
  		}
  		else
  		{
  			if(!bHeaderSuppressionEnabled)
  			{
  				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nHeader Suppression Disabled For SF: No PHS\n");
  			}
  
  			return STATUS_SUCCESS;
  		}
  	}
  
  	//BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHSTransmit : Dumping data packet After PHS");
  	return STATUS_SUCCESS;
  }
  
  int PHSRecieve(PMINI_ADAPTER Adapter,
  					USHORT usVcid,
  					struct sk_buff *packet,
  					UINT *punPacketLen,
  					UCHAR *pucEthernetHdr,
  					UINT	bHeaderSuppressionEnabled)
  {
  	u32   nStandardPktHdrLen            		= 0;
  	u32   nTotalsupressedPktHdrBytes  = 0;
  	int     ulPhsStatus 		= 0;
  	PUCHAR pucInBuff = NULL ;
  	UINT TotalBytesAdded = 0;
  	if(!bHeaderSuppressionEnabled)
  	{
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nPhs Disabled for incoming packet");
  		return ulPhsStatus;
  	}
  
  	pucInBuff = packet->data;
  
  	//Restore  PHS suppressed header
  	nStandardPktHdrLen = packet->len;
  	ulPhsStatus = PhsDeCompress(&Adapter->stBCMPhsContext,
  		usVcid,
  		pucInBuff,
  		Adapter->ucaPHSPktRestoreBuf,
  		&nTotalsupressedPktHdrBytes,
  		&nStandardPktHdrLen);
  
  	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nSupressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
  					nTotalsupressedPktHdrBytes,nStandardPktHdrLen);
  
  	if(ulPhsStatus != STATUS_PHS_COMPRESSED)
  	{
  		skb_pull(packet, 1);
  		return STATUS_SUCCESS;
  	}
  	else
  	{
  		TotalBytesAdded = nStandardPktHdrLen - nTotalsupressedPktHdrBytes - PHSI_LEN;
  		if(TotalBytesAdded)
  		{
  			if(skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded))
  				skb_push(packet, TotalBytesAdded);
  			else
  			{
  				if(skb_cow(packet, skb_headroom(packet) + TotalBytesAdded))
  				{
  					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "cow failed in receive\n");
  					return STATUS_FAILURE;
  				}
  
  				skb_push(packet, TotalBytesAdded);
  			}
  		}
  
  		memcpy(packet->data, Adapter->ucaPHSPktRestoreBuf, nStandardPktHdrLen);
  	}
  
  	return STATUS_SUCCESS;
  }
  
  void DumpFullPacket(UCHAR *pBuf,UINT nPktLen)
  {
  	PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
      BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"Dumping Data Packet");
      BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,pBuf,nPktLen);
  }
  
  //-----------------------------------------------------------------------------
  // Procedure:   phs_init
  //
  // Description: This routine is responsible for allocating memory for classifier and
  // PHS rules.
  //
  // Arguments:
  // pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules and PHS Rules , RX, TX buffer etc
  //
  // Returns:
  // TRUE(1)	-If allocation of memory was success full.
  // FALSE	-If allocation of memory fails.
  //-----------------------------------------------------------------------------
  int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension,PMINI_ADAPTER Adapter)
  {
  	int i;
  	S_SERVICEFLOW_TABLE *pstServiceFlowTable;
      BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nPHS:phs_init function ");
  
  	if(pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
  		return -EINVAL;
  
  	pPhsdeviceExtension->pstServiceFlowPhsRulesTable =
  		kzalloc(sizeof(S_SERVICEFLOW_TABLE), GFP_KERNEL);
  
      if(!pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
  	{
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation ServiceFlowPhsRulesTable failed");
  		return -ENOMEM;
  	}
  
  	pstServiceFlowTable = pPhsdeviceExtension->pstServiceFlowPhsRulesTable;
  	for(i=0;i<MAX_SERVICEFLOWS;i++)
  	{
  		S_SERVICEFLOW_ENTRY sServiceFlow = pstServiceFlowTable->stSFList[i];
  		sServiceFlow.pstClassifierTable = kzalloc(sizeof(S_CLASSIFIER_TABLE), GFP_KERNEL);
  		if(!sServiceFlow.pstClassifierTable)
  		{
  			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
  			free_phs_serviceflow_rules(pPhsdeviceExtension->
                  pstServiceFlowPhsRulesTable);
  			pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
  			return -ENOMEM;
  		}
  	}
  
  	pPhsdeviceExtension->CompressedTxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
  
      if(pPhsdeviceExtension->CompressedTxBuffer == NULL)
  	{
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
  		free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
  		pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
  		return -ENOMEM;
  	}
  
      pPhsdeviceExtension->UnCompressedRxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
  	if(pPhsdeviceExtension->UnCompressedRxBuffer == NULL)
  	{
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
  		kfree(pPhsdeviceExtension->CompressedTxBuffer);
  		free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
  		pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
  		return -ENOMEM;
  	}
  
  
  
  	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successfull");
  	return STATUS_SUCCESS;
  }
  
  
  int PhsCleanup(IN PPHS_DEVICE_EXTENSION pPHSDeviceExt)
  {
  	if(pPHSDeviceExt->pstServiceFlowPhsRulesTable)
  	{
  		free_phs_serviceflow_rules(pPHSDeviceExt->pstServiceFlowPhsRulesTable);
  		pPHSDeviceExt->pstServiceFlowPhsRulesTable = NULL;
  	}
  
  	kfree(pPHSDeviceExt->CompressedTxBuffer);
  	pPHSDeviceExt->CompressedTxBuffer = NULL;
  
  	kfree(pPHSDeviceExt->UnCompressedRxBuffer);
  	pPHSDeviceExt->UnCompressedRxBuffer = NULL;
  
  	return 0;
  }
  
  
  
  //PHS functions
  /*++
  PhsUpdateClassifierRule
  
  Routine Description:
      Exported function to add or modify a PHS Rule.
  
  Arguments:
  	IN void* pvContext - PHS Driver Specific Context
  	IN B_UINT16 uiVcid    - The Service Flow ID for which the PHS rule applies
  	IN B_UINT16  uiClsId   - The Classifier ID within the Service Flow for which the PHS rule applies.
  	IN S_PHS_RULE *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table.
  
  Return Value:
  
      0 if successful,
      >0 Error.
  
  --*/
  ULONG PhsUpdateClassifierRule(IN void* pvContext,
  								IN B_UINT16  uiVcid ,
  								IN B_UINT16  uiClsId   ,
  								IN S_PHS_RULE *psPhsRule,
  								IN B_UINT8  u8AssociatedPHSI)
  {
  	ULONG lStatus =0;
  	UINT nSFIndex =0 ;
  	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
      PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
  
  
  
  	PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
  
  	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"PHS With Corr2 Changes \n");
  
  	if(pDeviceExtension == NULL)
  	{
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Invalid Device Extension\n");
  		return ERR_PHS_INVALID_DEVICE_EXETENSION;
  	}
  
  
  	if(u8AssociatedPHSI == 0)
  	{
  		return ERR_PHS_INVALID_PHS_RULE;
  	}
  
  	/* Retrieve the SFID Entry Index for requested Service Flow */
  
  	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
  	                uiVcid,&pstServiceFlowEntry);
  
      if(nSFIndex == PHS_INVALID_TABLE_INDEX)
  	{
  		/* This is a new SF. Create a mapping entry for this */
  		lStatus = CreateSFToClassifierRuleMapping(uiVcid, uiClsId,
  		      pDeviceExtension->pstServiceFlowPhsRulesTable, psPhsRule, u8AssociatedPHSI);
  		return lStatus;
  	}
  
  	/* SF already Exists Add PHS Rule to existing SF */
    	lStatus = CreateClassiferToPHSRuleMapping(uiVcid, uiClsId,
    	          pstServiceFlowEntry, psPhsRule, u8AssociatedPHSI);
  
      return lStatus;
  }
  
  /*++
  PhsDeletePHSRule
  
  Routine Description:
     Deletes the specified phs Rule within Vcid
  
  Arguments:
  	IN void* pvContext - PHS Driver Specific Context
  	IN B_UINT16  uiVcid    - The Service Flow ID for which the PHS rule applies
  	IN B_UINT8  u8PHSI   - the PHS Index identifying PHS rule to be deleted.
  
  Return Value:
  
      0 if successful,
      >0 Error.
  
  --*/
  
  ULONG PhsDeletePHSRule(IN void* pvContext,IN B_UINT16 uiVcid,IN B_UINT8 u8PHSI)
  {
  	ULONG lStatus =0;
  	UINT nSFIndex =0, nClsidIndex =0 ;
  	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
  	S_CLASSIFIER_TABLE *pstClassifierRulesTable = NULL;
      PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
  
  
  	PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
  
  	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "======>\n");
  
  	if(pDeviceExtension)
  	{
  
  		//Retrieve the SFID Entry Index for requested Service Flow
  		nSFIndex = GetServiceFlowEntry(pDeviceExtension
  		      ->pstServiceFlowPhsRulesTable,uiVcid,&pstServiceFlowEntry);
  
         if(nSFIndex == PHS_INVALID_TABLE_INDEX)
  		{
  			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
  			return ERR_SF_MATCH_FAIL;
  		}
  
  		pstClassifierRulesTable=pstServiceFlowEntry->pstClassifierTable;
  		if(pstClassifierRulesTable)
  		{
  			for(nClsidIndex=0;nClsidIndex<MAX_PHSRULE_PER_SF;nClsidIndex++)
  			{
  				if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].bUsed && pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule)
  				{
  					if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8PHSI == u8PHSI)					{
  						if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
  							pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt--;
  						if(0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule->u8RefCnt)
  							kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);
  						memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0,
  							sizeof(S_CLASSIFIER_ENTRY));
  					}
  				}
  			}
  		}
  
  	}
  	return lStatus;
  }
  
  /*++
  PhsDeleteClassifierRule
  
  Routine Description:
      Exported function to Delete a PHS Rule for the SFID,CLSID Pair.
  
  Arguments:
  	IN void* pvContext - PHS Driver Specific Context
  	IN B_UINT16  uiVcid    - The Service Flow ID for which the PHS rule applies
  	IN B_UINT16  uiClsId   - The Classifier ID within the Service Flow for which the PHS rule applies.
  
  Return Value:
  
      0 if successful,
      >0 Error.
  
  --*/
  ULONG PhsDeleteClassifierRule(IN void* pvContext,IN B_UINT16 uiVcid ,IN B_UINT16  uiClsId)
  {
  	ULONG lStatus =0;
  	UINT nSFIndex =0, nClsidIndex =0 ;
  	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
  	S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL;
      PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
  	PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
  
  	if(pDeviceExtension)
  	{
  		//Retrieve the SFID Entry Index for requested Service Flow
  		nSFIndex = GetServiceFlowEntry(pDeviceExtension
  		      ->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry);
  		if(nSFIndex == PHS_INVALID_TABLE_INDEX)
  		{
  			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"SFID Match Failed\n");
  			return ERR_SF_MATCH_FAIL;
  		}
  
  		nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
                    uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry);
  		if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule))
  		{
  			if(pstClassifierEntry->pstPhsRule)
  			{
  				if(pstClassifierEntry->pstPhsRule->u8RefCnt)
  				pstClassifierEntry->pstPhsRule->u8RefCnt--;
  				if(0==pstClassifierEntry->pstPhsRule->u8RefCnt)
  					kfree(pstClassifierEntry->pstPhsRule);
  
  			}
  			memset(pstClassifierEntry, 0, sizeof(S_CLASSIFIER_ENTRY));
  		}
  
  		nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
                      uiClsId,eOldClassifierRuleContext,&pstClassifierEntry);
  
  	   if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule))
  		{
  			kfree(pstClassifierEntry->pstPhsRule);
  			memset(pstClassifierEntry, 0, sizeof(S_CLASSIFIER_ENTRY));
  		}
  	}
  	return lStatus;
  }
  
  /*++
  PhsDeleteSFRules
  
  Routine Description:
      Exported function to Delete a all PHS Rules for the SFID.
  
  Arguments:
  	IN void* pvContext - PHS Driver Specific Context
  	IN B_UINT16 uiVcid   - The Service Flow ID for which the PHS rules need to be deleted
  
  Return Value:
  
      0 if successful,
      >0 Error.
  
  --*/
  ULONG PhsDeleteSFRules(IN void* pvContext,IN B_UINT16 uiVcid)
  {
  
  	ULONG lStatus =0;
  	UINT nSFIndex =0, nClsidIndex =0  ;
  	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
  	S_CLASSIFIER_TABLE *pstClassifierRulesTable = NULL;
      PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
  	PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
      BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"====> \n");
  
  	if(pDeviceExtension)
  	{
  		//Retrieve the SFID Entry Index for requested Service Flow
  		nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
  		                  uiVcid,&pstServiceFlowEntry);
  		if(nSFIndex == PHS_INVALID_TABLE_INDEX)
  		{
  			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n");
  			return ERR_SF_MATCH_FAIL;
  		}
  
  		pstClassifierRulesTable=pstServiceFlowEntry->pstClassifierTable;
  		if(pstClassifierRulesTable)
  		{
  			for(nClsidIndex=0;nClsidIndex<MAX_PHSRULE_PER_SF;nClsidIndex++)
  			{
  				if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule)
  				{
  					if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
                                                          .pstPhsRule->u8RefCnt)
  						pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
  						                                    .pstPhsRule->u8RefCnt--;
  					if(0==pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
                                                            .pstPhsRule->u8RefCnt)
  						kfree(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule);
  					    pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
                                          .pstPhsRule = NULL;
  				}
  				memset(&pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex], 0, sizeof(S_CLASSIFIER_ENTRY));
  				if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule)
  				{
  					if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
                                          .pstPhsRule->u8RefCnt)
  						pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
  						                  .pstPhsRule->u8RefCnt--;
  					if(0 == pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
                                          .pstPhsRule->u8RefCnt)
  						kfree(pstClassifierRulesTable
  						      ->stOldPhsRulesList[nClsidIndex].pstPhsRule);
  					pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
                                .pstPhsRule = NULL;
  				}
  				memset(&pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex], 0, sizeof(S_CLASSIFIER_ENTRY));
  			}
  		}
  		pstServiceFlowEntry->bUsed = FALSE;
  		pstServiceFlowEntry->uiVcid = 0;
  
  	}
  
  	return lStatus;
  }
  
  
  /*++
  PhsCompress
  
  Routine Description:
      Exported function to compress the data using PHS.
  
  Arguments:
  	IN void* pvContext - PHS Driver Specific Context.
  	IN B_UINT16 uiVcid    - The Service Flow ID to which current packet header compression applies.
  	IN UINT  uiClsId   - The Classifier ID to which current packet header compression applies.
  	IN void *pvInputBuffer - The Input buffer containg packet header data
  	IN void *pvOutputBuffer - The output buffer returned by this function after PHS
  	IN UINT *pOldHeaderSize  - The actual size of the header before PHS
  	IN UINT *pNewHeaderSize - The new size of the header after applying PHS
  
  Return Value:
  
      0 if successful,
      >0 Error.
  
  --*/
  ULONG PhsCompress(IN void* pvContext,
  				  IN B_UINT16 uiVcid,
  				  IN B_UINT16 uiClsId,
  				  IN void *pvInputBuffer,
  				  OUT void *pvOutputBuffer,
  				  OUT UINT *pOldHeaderSize,
  				  OUT UINT *pNewHeaderSize )
  {
  	UINT nSFIndex =0, nClsidIndex =0  ;
  	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
  	S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL;
  	S_PHS_RULE *pstPhsRule = NULL;
  	ULONG lStatus =0;
      PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
  
  
  
  	PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext;
  
  
  	if(pDeviceExtension == NULL)
  	{
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Invalid Device Extension\n");
  		lStatus =  STATUS_PHS_NOCOMPRESSION ;
  		return lStatus;
  
  	}
  
  	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Suppressing header \n");
  
  
  	//Retrieve the SFID Entry Index for requested Service Flow
  	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
  	                  uiVcid,&pstServiceFlowEntry);
  	if(nSFIndex == PHS_INVALID_TABLE_INDEX)
  	{
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"SFID Match Failed\n");
  		lStatus =  STATUS_PHS_NOCOMPRESSION ;
  		return lStatus;
  	}
  
  	nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
                  uiClsId,eActiveClassifierRuleContext,&pstClassifierEntry);
  
      if(nClsidIndex == PHS_INVALID_TABLE_INDEX)
  	{
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"No PHS Rule Defined For Classifier\n");
  		lStatus =  STATUS_PHS_NOCOMPRESSION ;
  		return lStatus;
  	}
  
  
  	//get rule from SF id,Cls ID pair and proceed
  	pstPhsRule =  pstClassifierEntry->pstPhsRule;
  
  	if(!ValidatePHSRuleComplete(pstPhsRule))
  	{
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"PHS Rule Defined For Classifier But Not Complete\n");
  		lStatus =  STATUS_PHS_NOCOMPRESSION ;
  		return lStatus;
  	}
  
  	//Compress Packet
  	lStatus = phs_compress(pstPhsRule,(PUCHAR)pvInputBuffer,
  	      (PUCHAR)pvOutputBuffer, pOldHeaderSize,pNewHeaderSize);
  
  	if(lStatus == STATUS_PHS_COMPRESSED)
  	{
  		pstPhsRule->PHSModifiedBytes += *pOldHeaderSize - *pNewHeaderSize - 1;
  		pstPhsRule->PHSModifiedNumPackets++;
  	}
  	else
  		pstPhsRule->PHSErrorNumPackets++;
  
  	return lStatus;
  }
  
  /*++
  PhsDeCompress
  
  Routine Description:
      Exported function to restore the packet header in Rx path.
  
  Arguments:
  	IN void* pvContext - PHS Driver Specific Context.
  	IN B_UINT16 uiVcid    - The Service Flow ID to which current packet header restoration applies.
  	IN  void *pvInputBuffer - The Input buffer containg suppressed packet header data
  	OUT void *pvOutputBuffer - The output buffer returned by this function after restoration
  	OUT UINT *pHeaderSize   - The packet header size after restoration is returned in this parameter.
  
  Return Value:
  
      0 if successful,
      >0 Error.
  
  --*/
  ULONG PhsDeCompress(IN void* pvContext,
  				  IN B_UINT16 uiVcid,
  				  IN void *pvInputBuffer,
  				  OUT void *pvOutputBuffer,
  				  OUT UINT *pInHeaderSize,
  				  OUT UINT *pOutHeaderSize )
  {
  	UINT nSFIndex =0, nPhsRuleIndex =0 ;
  	S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL;
  	S_PHS_RULE *pstPhsRule = NULL;
  	UINT phsi;
      PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
  	PPHS_DEVICE_EXTENSION pDeviceExtension=
          (PPHS_DEVICE_EXTENSION)pvContext;
  
  	*pInHeaderSize = 0;
  
  	if(pDeviceExtension == NULL)
  	{
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"Invalid Device Extension\n");
  		return ERR_PHS_INVALID_DEVICE_EXETENSION;
  	}
  
  	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"Restoring header \n");
  
  	phsi = *((unsigned char *)(pvInputBuffer));
      BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"PHSI To Be Used For restore : %x \n",phsi);
      if(phsi == UNCOMPRESSED_PACKET )
  	{
  		return STATUS_PHS_NOCOMPRESSION;
  	}
  
  	//Retrieve the SFID Entry Index for requested Service Flow
  	nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
  	      uiVcid,&pstServiceFlowEntry);
  	if(nSFIndex == PHS_INVALID_TABLE_INDEX)
  	{
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"SFID Match Failed During Lookup\n");
  		return ERR_SF_MATCH_FAIL;
  	}
  
  	nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,phsi,
            eActiveClassifierRuleContext,&pstPhsRule);
  	if(nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
  	{
  		//Phs Rule does not exist in  active rules table. Lets try in the old rules table.
  		nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,
  		      phsi,eOldClassifierRuleContext,&pstPhsRule);
  		if(nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
  		{
  			return ERR_PHSRULE_MATCH_FAIL;
  		}
  
  	}
  
  	*pInHeaderSize = phs_decompress((PUCHAR)pvInputBuffer,
              (PUCHAR)pvOutputBuffer,pstPhsRule,pOutHeaderSize);
  
  	pstPhsRule->PHSModifiedBytes += *pOutHeaderSize - *pInHeaderSize - 1;
  
  	pstPhsRule->PHSModifiedNumPackets++;
  	return STATUS_PHS_COMPRESSED;
  }
  
  
  //-----------------------------------------------------------------------------
  // Procedure:   free_phs_serviceflow_rules
  //
  // Description: This routine is responsible for freeing memory allocated for PHS rules.
  //
  // Arguments:
  // rules	- ptr to S_SERVICEFLOW_TABLE structure.
  //
  // Returns:
  // Does not return any value.
  //-----------------------------------------------------------------------------
  
  static void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable)
  {
  	int i,j;
      PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
  
  	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "=======>\n");
      if(psServiceFlowRulesTable)
  	{
  		for(i=0;i<MAX_SERVICEFLOWS;i++)
  		{
  			S_SERVICEFLOW_ENTRY stServiceFlowEntry =
                  psServiceFlowRulesTable->stSFList[i];
  			S_CLASSIFIER_TABLE *pstClassifierRulesTable =
                  stServiceFlowEntry.pstClassifierTable;
  
  			if(pstClassifierRulesTable)
  			{
  				for(j=0;j<MAX_PHSRULE_PER_SF;j++)
  				{
  					if(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule)
  					{
  						if(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
                                                                                          ->u8RefCnt)
  							pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
    							                                                ->u8RefCnt--;
  						if(0==pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule
                                                                  ->u8RefCnt)
  							kfree(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule);
  						pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule = NULL;
  					}
  					if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule)
  					{
  						if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
                                                                  ->u8RefCnt)
  							pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
  							                                          ->u8RefCnt--;
  						if(0==pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule
                                                                        ->u8RefCnt)
  							kfree(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule);
  						pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule = NULL;
  					}
  				}
  				kfree(pstClassifierRulesTable);
  			    stServiceFlowEntry.pstClassifierTable = pstClassifierRulesTable = NULL;
  			}
  		}
  	}
  
      kfree(psServiceFlowRulesTable);
      psServiceFlowRulesTable = NULL;
  }
  
  
  
  static BOOLEAN ValidatePHSRuleComplete(IN S_PHS_RULE *psPhsRule)
  {
  	if(psPhsRule)
  	{
  		if(!psPhsRule->u8PHSI)
  		{
  			// PHSI is not valid
  			return FALSE;
  		}
  
  		if(!psPhsRule->u8PHSS)
  		{
  			//PHSS Is Undefined
  			return FALSE;
  		}
  
  		//Check if PHSF is defines for the PHS Rule
  		if(!psPhsRule->u8PHSFLength) // If any part of PHSF is valid then Rule contains valid PHSF
  		{
  			return FALSE;
  		}
  		return TRUE;
  	}
  	else
  	{
  		return FALSE;
  	}
  }
  
  UINT GetServiceFlowEntry(IN S_SERVICEFLOW_TABLE *psServiceFlowTable,
      IN B_UINT16 uiVcid,S_SERVICEFLOW_ENTRY **ppstServiceFlowEntry)
  {
  	int  i;
  	for(i=0;i<MAX_SERVICEFLOWS;i++)
  	{
  		if(psServiceFlowTable->stSFList[i].bUsed)
  		{
  			if(psServiceFlowTable->stSFList[i].uiVcid == uiVcid)
  			{
  				*ppstServiceFlowEntry = &psServiceFlowTable->stSFList[i];
  				return i;
  			}
  		}
  	}
  
  	*ppstServiceFlowEntry = NULL;
  	return PHS_INVALID_TABLE_INDEX;
  }
  
  
  UINT GetClassifierEntry(IN S_CLASSIFIER_TABLE *pstClassifierTable,
          IN B_UINT32 uiClsid,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,
          OUT S_CLASSIFIER_ENTRY **ppstClassifierEntry)
  {
  	int  i;
  	S_CLASSIFIER_ENTRY *psClassifierRules = NULL;
  	for(i=0;i<MAX_PHSRULE_PER_SF;i++)
  	{
  
  		if(eClsContext == eActiveClassifierRuleContext)
  		{
  			psClassifierRules = &pstClassifierTable->stActivePhsRulesList[i];
  		}
  		else
  		{
  			psClassifierRules = &pstClassifierTable->stOldPhsRulesList[i];
  		}
  
  		if(psClassifierRules->bUsed)
  		{
  			if(psClassifierRules->uiClassifierRuleId == uiClsid)
  			{
  				*ppstClassifierEntry = psClassifierRules;
  				return i;
  			}
  		}
  
  	}
  
  	*ppstClassifierEntry = NULL;
  	return PHS_INVALID_TABLE_INDEX;
  }
  
  static UINT GetPhsRuleEntry(IN S_CLASSIFIER_TABLE *pstClassifierTable,
  			    IN B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,
  			    OUT S_PHS_RULE **ppstPhsRule)
  {
  	int  i;
  	S_CLASSIFIER_ENTRY *pstClassifierRule = NULL;
  	for(i=0;i<MAX_PHSRULE_PER_SF;i++)
  	{
  		if(eClsContext == eActiveClassifierRuleContext)
  		{
  			pstClassifierRule = &pstClassifierTable->stActivePhsRulesList[i];
  		}
  		else
  		{
  			pstClassifierRule = &pstClassifierTable->stOldPhsRulesList[i];
  		}
  		if(pstClassifierRule->bUsed)
  		{
  			if(pstClassifierRule->u8PHSI == uiPHSI)
  			{
  				*ppstPhsRule = pstClassifierRule->pstPhsRule;
  				return i;
  			}
  		}
  
  	}
  
  	*ppstPhsRule = NULL;
  	return PHS_INVALID_TABLE_INDEX;
  }
  
  UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid,IN B_UINT16  uiClsId,
                        IN S_SERVICEFLOW_TABLE *psServiceFlowTable,S_PHS_RULE *psPhsRule,
                        B_UINT8 u8AssociatedPHSI)
  {
  
      S_CLASSIFIER_TABLE *psaClassifiertable = NULL;
  	UINT uiStatus = 0;
  	int iSfIndex;
  	BOOLEAN bFreeEntryFound =FALSE;
  	//Check for a free entry in SFID table
  	for(iSfIndex=0;iSfIndex < MAX_SERVICEFLOWS;iSfIndex++)
  	{
  		if(!psServiceFlowTable->stSFList[iSfIndex].bUsed)
  		{
  			bFreeEntryFound = TRUE;
  			break;
  		}
  	}
  
  	if(!bFreeEntryFound)
  		return ERR_SFTABLE_FULL;
  
  
  	psaClassifiertable = psServiceFlowTable->stSFList[iSfIndex].pstClassifierTable;
  	uiStatus = CreateClassifierPHSRule(uiClsId,psaClassifiertable,psPhsRule,
  	                      eActiveClassifierRuleContext,u8AssociatedPHSI);
  	if(uiStatus == PHS_SUCCESS)
  	{
  		//Add entry at free index to the SF
  		psServiceFlowTable->stSFList[iSfIndex].bUsed = TRUE;
  		psServiceFlowTable->stSFList[iSfIndex].uiVcid = uiVcid;
  	}
  
  	return uiStatus;
  
  }
  
  UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,
              IN B_UINT16  uiClsId,IN S_SERVICEFLOW_ENTRY *pstServiceFlowEntry,
                S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI)
  {
  	S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL;
  	UINT uiStatus =PHS_SUCCESS;
  	UINT nClassifierIndex = 0;
  	S_CLASSIFIER_TABLE *psaClassifiertable = NULL;
      PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
      psaClassifiertable = pstServiceFlowEntry->pstClassifierTable;
  
  	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "==>");
  
  	/* Check if the supplied Classifier already exists */
  	nClassifierIndex =GetClassifierEntry(
  	            pstServiceFlowEntry->pstClassifierTable,uiClsId,
  	            eActiveClassifierRuleContext,&pstClassifierEntry);
  	if(nClassifierIndex == PHS_INVALID_TABLE_INDEX)
  	{
  		/*
  		    The Classifier doesn't exist. So its a new classifier being added.
  		     Add new entry to associate PHS Rule to the Classifier
  		*/
  
  		uiStatus = CreateClassifierPHSRule(uiClsId,psaClassifiertable,
  		    psPhsRule,eActiveClassifierRuleContext,u8AssociatedPHSI);
  		return uiStatus;
  	}
  
  	/*
  	  The Classifier exists.The PHS Rule for this classifier
  	  is being modified
  	  */
  	if(pstClassifierEntry->u8PHSI == psPhsRule->u8PHSI)
  	{
  		if(pstClassifierEntry->pstPhsRule == NULL)
  			return ERR_PHS_INVALID_PHS_RULE;
  
  		/*
  		    This rule already exists if any fields are changed for this PHS
  		    rule update them.
  		 */
  		 /* If any part of PHSF is valid then we update PHSF */
  		if(psPhsRule->u8PHSFLength)
  		{
  			//update PHSF
  			memcpy(pstClassifierEntry->pstPhsRule->u8PHSF,
  			    psPhsRule->u8PHSF , MAX_PHS_LENGTHS);
  		}
  		if(psPhsRule->u8PHSFLength)
  		{
  			//update PHSFLen
  			pstClassifierEntry->pstPhsRule->u8PHSFLength =
  			    psPhsRule->u8PHSFLength;
  		}
  		if(psPhsRule->u8PHSMLength)
  		{
  			//update PHSM
  			memcpy(pstClassifierEntry->pstPhsRule->u8PHSM,
  			    psPhsRule->u8PHSM, MAX_PHS_LENGTHS);
  		}
  		if(psPhsRule->u8PHSMLength)
  		{
  			//update PHSM Len
  			pstClassifierEntry->pstPhsRule->u8PHSMLength =
  			    psPhsRule->u8PHSMLength;
  		}
  		if(psPhsRule->u8PHSS)
  		{
  			//update PHSS
  			pstClassifierEntry->pstPhsRule->u8PHSS = psPhsRule->u8PHSS;
  		}
  
  		//update PHSV
  		pstClassifierEntry->pstPhsRule->u8PHSV = psPhsRule->u8PHSV;
  
  	}
  	else
  	{
  		/*
  		  A new rule is being set for this classifier.
  		*/
  		uiStatus=UpdateClassifierPHSRule( uiClsId,  pstClassifierEntry,
  		      psaClassifiertable,  psPhsRule, u8AssociatedPHSI);
  	}
  
  
  
  	return uiStatus;
  }
  
  static UINT CreateClassifierPHSRule(IN B_UINT16  uiClsId,
      S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,
      E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI)
  {
  	UINT iClassifierIndex = 0;
  	BOOLEAN bFreeEntryFound = FALSE;
  	S_CLASSIFIER_ENTRY *psClassifierRules = NULL;
  	UINT nStatus = PHS_SUCCESS;
      PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
  	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Inside CreateClassifierPHSRule");
      if(psaClassifiertable == NULL)
  	{
  		return ERR_INVALID_CLASSIFIERTABLE_FOR_SF;
  	}
  
  	if(eClsContext == eOldClassifierRuleContext)
  	{
  		/* If An Old Entry for this classifier ID already exists in the
  		    old rules table replace it. */
  
  		iClassifierIndex =
  		GetClassifierEntry(psaClassifiertable, uiClsId,
  		            eClsContext,&psClassifierRules);
  		if(iClassifierIndex != PHS_INVALID_TABLE_INDEX)
  		{
  			/*
  			    The Classifier already exists in the old rules table
  		        Lets replace the old classifier with the new one.
  			*/
  			bFreeEntryFound = TRUE;
  		}
  	}
  
  	if(!bFreeEntryFound)
  	{
  		/*
  		  Continue to search for a free location to add the rule
  		*/
  		for(iClassifierIndex = 0; iClassifierIndex <
              MAX_PHSRULE_PER_SF; iClassifierIndex++)
  		{
  			if(eClsContext == eActiveClassifierRuleContext)
  			{
  				psClassifierRules =
                &psaClassifiertable->stActivePhsRulesList[iClassifierIndex];
  			}
  			else
  			{
  				psClassifierRules =
                  &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
  			}
  
  			if(!psClassifierRules->bUsed)
  			{
  				bFreeEntryFound = TRUE;
  				break;
  			}
  		}
  	}
  
  	if(!bFreeEntryFound)
  	{
  		if(eClsContext == eActiveClassifierRuleContext)
  		{
  			return ERR_CLSASSIFIER_TABLE_FULL;
  		}
  		else
  		{
  			//Lets replace the oldest rule if we are looking in old Rule table
  			if(psaClassifiertable->uiOldestPhsRuleIndex >=
                  MAX_PHSRULE_PER_SF)
  			{
  				psaClassifiertable->uiOldestPhsRuleIndex =0;
  			}
  
  			iClassifierIndex = psaClassifiertable->uiOldestPhsRuleIndex;
  			psClassifierRules =
                &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
  
            (psaClassifiertable->uiOldestPhsRuleIndex)++;
  		}
  	}
  
  	if(eClsContext == eOldClassifierRuleContext)
  	{
  		if(psClassifierRules->pstPhsRule == NULL)
  		{
  			psClassifierRules->pstPhsRule = kmalloc(sizeof(S_PHS_RULE),GFP_KERNEL);
  
            if(NULL == psClassifierRules->pstPhsRule)
  				return ERR_PHSRULE_MEMALLOC_FAIL;
  		}
  
  		psClassifierRules->bUsed = TRUE;
  		psClassifierRules->uiClassifierRuleId = uiClsId;
  		psClassifierRules->u8PHSI = psPhsRule->u8PHSI;
  		psClassifierRules->bUnclassifiedPHSRule = psPhsRule->bUnclassifiedPHSRule;
  
          /* Update The PHS rule */
  		memcpy(psClassifierRules->pstPhsRule,
  		    psPhsRule, sizeof(S_PHS_RULE));
  	}
  	else
  	{
  		nStatus = UpdateClassifierPHSRule(uiClsId,psClassifierRules,
              psaClassifiertable,psPhsRule,u8AssociatedPHSI);
  	}
  	return nStatus;
  }
  
  
  static UINT UpdateClassifierPHSRule(IN B_UINT16  uiClsId,
        IN S_CLASSIFIER_ENTRY *pstClassifierEntry,
        S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,
        B_UINT8 u8AssociatedPHSI)
  {
  	S_PHS_RULE *pstAddPhsRule = NULL;
  	UINT              nPhsRuleIndex = 0;
  	BOOLEAN       bPHSRuleOrphaned = FALSE;
      PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
  	psPhsRule->u8RefCnt =0;
  
  	/* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry*/
  	bPHSRuleOrphaned = DerefPhsRule( uiClsId, psaClassifiertable,
  	    pstClassifierEntry->pstPhsRule);
  
  	//Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in Classifier table for this SF
  	nPhsRuleIndex =GetPhsRuleEntry(psaClassifiertable,u8AssociatedPHSI,
  	    eActiveClassifierRuleContext, &pstAddPhsRule);
  	if(PHS_INVALID_TABLE_INDEX == nPhsRuleIndex)
  	{
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAdding New PHSRuleEntry For Classifier");
  
  		if(psPhsRule->u8PHSI == 0)
  		{
  			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nError PHSI is Zero\n");
  			return ERR_PHS_INVALID_PHS_RULE;
  		}
  		//Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId
  		if(FALSE == bPHSRuleOrphaned)
  		{
  			pstClassifierEntry->pstPhsRule = kmalloc(sizeof(S_PHS_RULE), GFP_KERNEL);
  			if(NULL == pstClassifierEntry->pstPhsRule)
  			{
  				return ERR_PHSRULE_MEMALLOC_FAIL;
  			}
  		}
  		memcpy(pstClassifierEntry->pstPhsRule, psPhsRule, sizeof(S_PHS_RULE));
  
  	}
  	else
  	{
  		//Step 2.b PHS Rule  Exists Tie uiClsId with the existing PHS Rule
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nTying Classifier to Existing PHS Rule");
  		if(bPHSRuleOrphaned)
  		{
  			kfree(pstClassifierEntry->pstPhsRule);
  			pstClassifierEntry->pstPhsRule = NULL;
  		}
  		pstClassifierEntry->pstPhsRule = pstAddPhsRule;
  
  	}
  	pstClassifierEntry->bUsed = TRUE;
  	pstClassifierEntry->u8PHSI = pstClassifierEntry->pstPhsRule->u8PHSI;
  	pstClassifierEntry->uiClassifierRuleId = uiClsId;
  	pstClassifierEntry->pstPhsRule->u8RefCnt++;
  	pstClassifierEntry->bUnclassifiedPHSRule = pstClassifierEntry->pstPhsRule->bUnclassifiedPHSRule;
  
  	return PHS_SUCCESS;
  
  }
  
  static BOOLEAN DerefPhsRule(IN B_UINT16  uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule)
  {
  	if(pstPhsRule==NULL)
  		return FALSE;
  	if(pstPhsRule->u8RefCnt)
  		pstPhsRule->u8RefCnt--;
  	if(0==pstPhsRule->u8RefCnt)
  	{
  		/*if(pstPhsRule->u8PHSI)
  		//Store the currently active rule into the old rules list
  		CreateClassifierPHSRule(uiClsId,psaClassifiertable,pstPhsRule,eOldClassifierRuleContext,pstPhsRule->u8PHSI);*/
  		return TRUE;
  	}
  	else
  	{
  		return FALSE;
  	}
  }
  
  void DumpPhsRules(PPHS_DEVICE_EXTENSION pDeviceExtension)
  {
  	int i,j,k,l;
      PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
      BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n Dumping PHS Rules : \n");
  	for(i=0;i<MAX_SERVICEFLOWS;i++)
  	{
  		S_SERVICEFLOW_ENTRY stServFlowEntry =
  				pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i];
  		if(stServFlowEntry.bUsed)
  		{
  			for(j=0;j<MAX_PHSRULE_PER_SF;j++)
  			{
  				for(l=0;l<2;l++)
  				{
  					S_CLASSIFIER_ENTRY stClsEntry;
  					if(l==0)
  					{
  						stClsEntry = stServFlowEntry.pstClassifierTable->stActivePhsRulesList[j];
  						if(stClsEntry.bUsed)
  							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Active PHS Rule : \n");
  					}
  					else
  					{
  						stClsEntry = stServFlowEntry.pstClassifierTable->stOldPhsRulesList[j];
  						if(stClsEntry.bUsed)
  							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Old PHS Rule : \n");
  					}
  					if(stClsEntry.bUsed)
  					{
  
  						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID  : %#X",stServFlowEntry.uiVcid);
  						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID  : %#X",stClsEntry.uiClassifierRuleId);
  						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID  : %#X",stClsEntry.u8PHSI);
  						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n");
  						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI  : %#X",stClsEntry.pstPhsRule->u8PHSI);
  						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ",stClsEntry.pstPhsRule->u8PHSFLength);
  						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : ");
  						for(k=0;k<stClsEntry.pstPhsRule->u8PHSFLength;k++)
  						{
  							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X  ",stClsEntry.pstPhsRule->u8PHSF[k]);
  						}
  						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength  : %#X",stClsEntry.pstPhsRule->u8PHSMLength);
  						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :");
  						for(k=0;k<stClsEntry.pstPhsRule->u8PHSMLength;k++)
  						{
  							BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X  ",stClsEntry.pstPhsRule->u8PHSM[k]);
  						}
  						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ",stClsEntry.pstPhsRule->u8PHSS);
  						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV  : %#X",stClsEntry.pstPhsRule->u8PHSV);
  						BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n");
  					}
  				}
  			}
  		}
  	}
  }
  
  
  //-----------------------------------------------------------------------------
  // Procedure:   phs_decompress
  //
  // Description: This routine restores the static fields within the packet.
  //
  // Arguments:
  //	in_buf			- ptr to incoming packet buffer.
  //	out_buf			- ptr to output buffer where the suppressed header is copied.
  //	decomp_phs_rules - ptr to PHS rule.
  //	header_size		- ptr to field which holds the phss or phsf_length.
  //
  // Returns:
  //	size -The number of bytes of dynamic fields present with in the incoming packet
  //			header.
  //	0	-If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed.
  //-----------------------------------------------------------------------------
  
  int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,
   S_PHS_RULE   *decomp_phs_rules,UINT *header_size)
  {
  	int phss,size=0;
  	 S_PHS_RULE   *tmp_memb;
  	int bit,i=0;
  	unsigned char *phsf,*phsm;
  	int in_buf_len = *header_size-1;
      PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
  	in_buf++;
      BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"====>\n");
  	*header_size = 0;
  
  	if((decomp_phs_rules == NULL ))
  		return 0;
  
  
  	tmp_memb = decomp_phs_rules;
  	//BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1  %d",phsi));
  	//*header_size = tmp_memb->u8PHSFLength;
  	phss         = tmp_memb->u8PHSS;
  	phsf         = tmp_memb->u8PHSF;
  	phsm         = tmp_memb->u8PHSM;
  
  	if(phss > MAX_PHS_LENGTHS)
  		phss = MAX_PHS_LENGTHS;
  	//BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI  %d phss %d index %d",phsi,phss,index));
  	while((phss > 0) && (size < in_buf_len))
  	{
  		bit =  ((*phsm << i)& SUPPRESS);
  
  		if(bit == SUPPRESS)
  		{
  			*out_buf = *phsf;
  			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phss  %d phsf %d ouput %d",
                phss,*phsf,*out_buf);
  		}
  		else
  		{
  			*out_buf = *in_buf;
  			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phss  %d input %d ouput %d",
              phss,*in_buf,*out_buf);
  			in_buf++;
  			size++;
  		}
  		out_buf++;
  		phsf++;
  		phss--;
  		i++;
  		*header_size=*header_size + 1;
  
  		if(i > MAX_NO_BIT)
  		{
  			i=0;
  			phsm++;
  		}
  	}
  	return size;
  }
  
  
  
  
  //-----------------------------------------------------------------------------
  // Procedure:   phs_compress
  //
  // Description: This routine suppresses the static fields within the packet.Before
  // that it will verify the fields to be suppressed with the corresponding fields in the
  // phsf. For verification it checks the phsv field of PHS rule. If set and verification
  // succeeds it suppresses the field.If any one static field is found different none of
  // the static fields are suppressed then the packet is sent as uncompressed packet with
  // phsi=0.
  //
  // Arguments:
  //	phs_rule - ptr to PHS rule.
  //	in_buf		- ptr to incoming packet buffer.
  //	out_buf		- ptr to output buffer where the suppressed header is copied.
  //	header_size	- ptr to field which holds the phss.
  //
  // Returns:
  //	size-The number of bytes copied into the output buffer i.e dynamic fields
  //	0	-If PHS rule is NULL.If PHSV field is not set.If the verification fails.
  //-----------------------------------------------------------------------------
  static int phs_compress(S_PHS_RULE  *phs_rule,unsigned char *in_buf
  			,unsigned char *out_buf,UINT *header_size,UINT *new_header_size)
  {
  	unsigned char *old_addr = out_buf;
  	int supress = 0;
      PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
      if(phs_rule == NULL)
  	{
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nphs_compress(): phs_rule null!");
  		*out_buf = ZERO_PHSI;
  		return STATUS_PHS_NOCOMPRESSION;
  	}
  
  
  	if(phs_rule->u8PHSS <= *new_header_size)
  	{
  		*header_size = phs_rule->u8PHSS;
  	}
  	else
  	{
  		*header_size = *new_header_size;
  	}
  	//To copy PHSI
  	out_buf++;
  	supress = verify_suppress_phsf(in_buf,out_buf,phs_rule->u8PHSF,
          phs_rule->u8PHSM, phs_rule->u8PHSS, phs_rule->u8PHSV,new_header_size);
  
  	if(supress == STATUS_PHS_COMPRESSED)
  	{
  		*old_addr = (unsigned char)phs_rule->u8PHSI;
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress phsi %d",phs_rule->u8PHSI);
  	}
  	else
  	{
  		*old_addr = ZERO_PHSI;
  		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress PHSV Verification failed");
  	}
  	return supress;
  }
  
  
  //-----------------------------------------------------------------------------
  // Procedure:	verify_suppress_phsf
  //
  // Description: This routine verifies the fields of the packet and if all the
  // static fields are equal it adds the phsi of that PHS rule.If any static
  // field differs it woun't suppress any field.
  //
  // Arguments:
  // rules_set	- ptr to classifier_rules.
  // in_buffer	- ptr to incoming packet buffer.
  // out_buffer	- ptr to output buffer where the suppressed header is copied.
  // phsf			- ptr to phsf.
  // phsm			- ptr to phsm.
  // phss			- variable holding phss.
  //
  // Returns:
  //	size-The number of bytes copied into the output buffer i.e dynamic fields.
  //	0	-Packet has failed the verification.
  //-----------------------------------------------------------------------------
  
  static int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer,
  				unsigned char *phsf,unsigned char *phsm,unsigned int phss,
  				unsigned int phsv,UINT* new_header_size)
  {
  	unsigned int size=0;
  	int bit,i=0;
      PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
      BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf PHSM - 0x%X",*phsm);
  
  
  	if(phss>(*new_header_size))
  	{
  		phss=*new_header_size;
  	}
  	while(phss > 0)
  	{
  		bit = ((*phsm << i)& SUPPRESS);
  		if(bit == SUPPRESS)
  		{
  
  			if(*in_buffer != *phsf)
  			{
  				if(phsv == VERIFY)
  				{
  					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf failed for field  %d buf  %d phsf %d",phss,*in_buffer,*phsf);
  					return STATUS_PHS_NOCOMPRESSION;
  				}
  			}
  			else
  				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf success for field  %d buf  %d phsf %d",phss,*in_buffer,*phsf);
  		}
  		else
  		{
  			*out_buffer = *in_buffer;
  			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In copying_header input %d  out %d",*in_buffer,*out_buffer);
  			out_buffer++;
  			size++;
  		}
  		in_buffer++;
  		phsf++;
  		phss--;
  		i++;
  		if(i > MAX_NO_BIT)
  		{
  			i=0;
  			phsm++;
  		}
  	}
  	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf success");
  	*new_header_size = size;
  	return STATUS_PHS_COMPRESSED;
  }
  
  
  
  
  
  
  