summaryrefslogtreecommitdiffstats
path: root/drivers/staging/bcm/PHSModule.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/bcm/PHSModule.c')
-rw-r--r--drivers/staging/bcm/PHSModule.c1641
1 files changed, 1641 insertions, 0 deletions
diff --git a/drivers/staging/bcm/PHSModule.c b/drivers/staging/bcm/PHSModule.c
new file mode 100644
index 000000000000..8a38cf43e795
--- /dev/null
+++ b/drivers/staging/bcm/PHSModule.c
@@ -0,0 +1,1641 @@
+#include "headers.h"
+
+#define IN
+#define OUT
+
+void DumpDataPacketHeader(PUCHAR pPkt);
+
+/*
+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))
+ {
+
+
+ //DumpDataPacketHeader(pucPHSPktHdrInBuf);
+
+ // 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;
+
+ bcm_kfree_skb(Packet);
+ *pPacket = Packet = newPacket;
+ pucPHSPktHdrInBuf = Packet->data + BytesToRemove;
+ }
+
+ numBytesCompressed = unPhsOldHdrSize - (unPHSNewPktHeaderLen+PHSI_LEN);
+
+ OsalMemMove(pucPHSPktHdrInBuf + numBytesCompressed, pucPHSPktHdrOutBuf, unPHSNewPktHeaderLen + PHSI_LEN);
+ OsalMemMove(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);
+ }
+ }
+
+ OsalMemMove(packet->data, Adapter->ucaPHSPktRestoreBuf, nStandardPktHdrLen);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+void DumpDataPacketHeader(PUCHAR pPkt)
+{
+ struct iphdr *iphd = (struct iphdr*)pPkt;
+ PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Phs Send/Recieve : IP Packet Hdr \n");
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"TOS : %x \n",iphd->tos);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Src IP : %x \n",iphd->saddr);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Dest IP : %x \n \n",iphd->daddr);
+
+}
+
+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 =
+ (S_SERVICEFLOW_TABLE*)OsalMemAlloc(sizeof(S_SERVICEFLOW_TABLE),
+ PHS_MEM_TAG);
+
+ if(pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
+ {
+ OsalZeroMemory(pPhsdeviceExtension->pstServiceFlowPhsRulesTable,
+ sizeof(S_SERVICEFLOW_TABLE));
+ }
+ else
+ {
+ 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 = (S_CLASSIFIER_TABLE*)OsalMemAlloc(
+ sizeof(S_CLASSIFIER_TABLE), PHS_MEM_TAG);
+ if(sServiceFlow.pstClassifierTable)
+ {
+ OsalZeroMemory(sServiceFlow.pstClassifierTable,sizeof(S_CLASSIFIER_TABLE));
+ pstServiceFlowTable->stSFList[i].pstClassifierTable = sServiceFlow.pstClassifierTable;
+ }
+ else
+ {
+ 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 =
+ OsalMemAlloc(PHS_BUFFER_SIZE,PHS_MEM_TAG);
+
+ 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 =
+ OsalMemAlloc(PHS_BUFFER_SIZE,PHS_MEM_TAG);
+ if(pPhsdeviceExtension->UnCompressedRxBuffer == NULL)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed");
+ OsalMemFree(pPhsdeviceExtension->CompressedTxBuffer,PHS_BUFFER_SIZE);
+ 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;
+ }
+
+ if(pPHSDeviceExt->CompressedTxBuffer)
+ {
+ OsalMemFree(pPHSDeviceExt->CompressedTxBuffer,PHS_BUFFER_SIZE);
+ pPHSDeviceExt->CompressedTxBuffer = NULL;
+ }
+ if(pPHSDeviceExt->UnCompressedRxBuffer)
+ {
+ OsalMemFree(pPHSDeviceExt->UnCompressedRxBuffer,PHS_BUFFER_SIZE);
+ 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)
+ OsalMemFree(pstClassifierRulesTable
+ ->stActivePhsRulesList[nClsidIndex].pstPhsRule,
+ sizeof(S_PHS_RULE));
+ OsalZeroMemory(&pstClassifierRulesTable
+ ->stActivePhsRulesList[nClsidIndex],
+ 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)
+ OsalMemFree(pstClassifierEntry->pstPhsRule,sizeof(S_PHS_RULE));
+
+ }
+ OsalZeroMemory(pstClassifierEntry,sizeof(S_CLASSIFIER_ENTRY));
+ }
+
+ nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
+ uiClsId,eOldClassifierRuleContext,&pstClassifierEntry);
+
+ if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule))
+ {
+ if(pstClassifierEntry->pstPhsRule)
+ //Delete the classifier entry
+ OsalMemFree(pstClassifierEntry->pstPhsRule,sizeof(S_PHS_RULE));
+ OsalZeroMemory(pstClassifierEntry,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)
+ OsalMemFree(pstClassifierRulesTable
+ ->stActivePhsRulesList[nClsidIndex].pstPhsRule,
+ sizeof(S_PHS_RULE));
+ pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex]
+ .pstPhsRule = NULL;
+ }
+ OsalZeroMemory(&pstClassifierRulesTable
+ ->stActivePhsRulesList[nClsidIndex],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)
+ OsalMemFree(pstClassifierRulesTable
+ ->stOldPhsRulesList[nClsidIndex].pstPhsRule,
+ sizeof(S_PHS_RULE));
+ pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex]
+ .pstPhsRule = NULL;
+ }
+ OsalZeroMemory(&pstClassifierRulesTable
+ ->stOldPhsRulesList[nClsidIndex],
+ 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.
+//-----------------------------------------------------------------------------
+
+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)
+ OsalMemFree(pstClassifierRulesTable->stActivePhsRulesList[j].
+ pstPhsRule, sizeof(S_PHS_RULE));
+ 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)
+ OsalMemFree(pstClassifierRulesTable->stOldPhsRulesList[j]
+ .pstPhsRule,sizeof(S_PHS_RULE));
+ pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule = NULL;
+ }
+ }
+ OsalMemFree(pstClassifierRulesTable,sizeof(S_CLASSIFIER_TABLE));
+ stServiceFlowEntry.pstClassifierTable = pstClassifierRulesTable = NULL;
+ }
+ }
+ }
+
+ OsalMemFree(psServiceFlowRulesTable,sizeof(S_SERVICEFLOW_TABLE));
+ psServiceFlowRulesTable = NULL;
+}
+
+
+
+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;
+}
+
+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
+ OsalMemMove(pstClassifierEntry->pstPhsRule->u8PHSF,
+ psPhsRule->u8PHSF , MAX_PHS_LENGTHS);
+ }
+ if(psPhsRule->u8PHSFLength)
+ {
+ //update PHSFLen
+ pstClassifierEntry->pstPhsRule->u8PHSFLength =
+ psPhsRule->u8PHSFLength;
+ }
+ if(psPhsRule->u8PHSMLength)
+ {
+ //update PHSM
+ OsalMemMove(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;
+}
+
+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 = (S_PHS_RULE*)OsalMemAlloc
+ (sizeof(S_PHS_RULE),PHS_MEM_TAG);
+
+ 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 */
+ OsalMemMove(psClassifierRules->pstPhsRule,
+ psPhsRule, sizeof(S_PHS_RULE));
+ }
+ else
+ {
+ nStatus = UpdateClassifierPHSRule(uiClsId,psClassifierRules,
+ psaClassifiertable,psPhsRule,u8AssociatedPHSI);
+ }
+ return nStatus;
+}
+
+
+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 = (S_PHS_RULE*)OsalMemAlloc(sizeof(S_PHS_RULE),PHS_MEM_TAG);
+ if(NULL == pstClassifierEntry->pstPhsRule)
+ {
+ return ERR_PHSRULE_MEMALLOC_FAIL;
+ }
+ }
+ OsalMemMove(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)
+ {
+ if(pstClassifierEntry->pstPhsRule)
+ {
+ //Just Free the PHS Rule as Ref Count is Zero
+ OsalMemFree(pstClassifierEntry->pstPhsRule,sizeof(S_PHS_RULE));
+ 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;
+
+}
+
+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;
+ }
+}
+
+static void DumpBuffer(PVOID BuffVAddress, int xferSize)
+{
+ int i;
+ int iPrintLength;
+ PUCHAR temp=(PUCHAR)BuffVAddress;
+ PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
+ iPrintLength=(xferSize<32?xferSize:32);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n");
+
+ for (i=0;i < iPrintLength;i++) {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "%x|",temp[i]);
+ }
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n");
+}
+
+
+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.
+//-----------------------------------------------------------------------------
+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.
+//-----------------------------------------------------------------------------
+
+ 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;
+}
+
+
+
+
+
+