extractedLnx/linux-2.6.36/drivers/staging/otus/80211core/ctxrx.c_zfiRecv80211.c
void zfiRecv80211(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo)
{
u8_t snapCase=0, encryMode;
u16_t frameType, typeLengthField;
u16_t frameCtrl;
u16_t frameSubtype;
u16_t ret;
u16_t len;
u8_t bIsDefrag = 0;
u16_t offset, tailLen;
u8_t vap = 0;
u16_t da[3], sa[3];
u16_t ii;
u8_t uapsdTrig = 0;
zbuf_t* psBuf;
#ifdef ZM_ENABLE_NATIVE_WIFI
u8_t i;
#endif
zmw_get_wlan_dev(dev);
ZM_BUFFER_TRACE(dev, buf)
//zm_msg2_rx(ZM_LV_2, "zfiRecv80211(), buf=", buf);
//zm_msg2_rx(ZM_LV_0, "h[0]=", zmw_rx_buf_readh(dev, buf, 0));
//zm_msg2_rx(ZM_LV_0, "h[2]=", zmw_rx_buf_readh(dev, buf, 2));
//zm_msg2_rx(ZM_LV_0, "h[4]=", zmw_rx_buf_readh(dev, buf, 4));
frameCtrl = zmw_rx_buf_readb(dev, buf, 0);
frameType = frameCtrl & 0xf;
frameSubtype = frameCtrl & 0xf0;
#if 0 // Move to ProcessBeacon to judge if there's a new peer station
if ( (wd->wlanMode == ZM_MODE_IBSS)&&
(wd->sta.ibssPartnerStatus != ZM_IBSS_PARTNER_ALIVE) )
{
zfStaIbssMonitoring(dev, buf);
}
#endif
/* If data frame */
if (frameType == ZM_WLAN_DATA_FRAME)
{
wd->sta.TotalNumberOfReceivePackets++;
wd->sta.TotalNumberOfReceiveBytes += zfwBufGetSize(dev, buf);
//zm_debug_msg1("Receive packets = ", wd->sta.TotalNumberOfReceivePackets);
//zm_msg0_rx(ZM_LV_0, "Rx data");
if (wd->wlanMode == ZM_MODE_AP)
{
ret = zfApUpdatePsBit(dev, buf, &vap, &uapsdTrig);
if (ret != ZM_SUCCESS)
{
zfwBufFree(dev, buf, 0);
return;
}
if (((uapsdTrig&0xf) != 0) && ((frameSubtype & 0x80) != 0))
{
u8_t ac = zcUpToAc[zmw_buf_readb(dev, buf, 24)&0x7];
u8_t pktNum;
u8_t mb;
u16_t flag;
u8_t src[6];
//printk("QoS ctrl=%d\n", zmw_buf_readb(dev, buf, 24));
//printk("UAPSD trigger, ac=%d\n", ac);
if (((0x8>>ac) & uapsdTrig) != 0)
{
pktNum = zcMaxspToPktNum[(uapsdTrig>>4) & 0x3];
for (ii=0; ii<6; ii++)
{
src[ii] = zmw_buf_readb(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+ii);
}
for (ii=0; ii<pktNum; ii++)
{
//if ((psBuf = zfQueueGet(dev, wd->ap.uapsdQ)) != NULL)
psBuf = zfQueueGetWithMac(dev, wd->ap.uapsdQ, src, &mb);
if (psBuf != NULL)
{
if ((ii+1) == pktNum)
{
//EOSP anyway
flag = 0x100 | (mb<<5);
}
else
{
if (mb != 0)
{
//more data, not EOSP
flag = 0x20;
}
else
{
//no more data, EOSP
flag = 0x100;
}
}
zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF, flag);
}
if ((psBuf == NULL) || (mb == 0))
{
if ((ii == 0) && (psBuf == NULL))
{
zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_QOS_NULL, (u16_t*)src, 0, 0, 0);
}
break;
}
}
}
}
}
else if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
{
u16_t frameCtrlMSB;
u8_t bssid[6];
/* Check Is RIFS frame and decide to enable RIFS or not */
if( wd->sta.EnableHT )
zfCheckIsRIFSFrame(dev, buf, frameSubtype);
if ( zfPowerSavingMgrIsSleeping(dev) || wd->sta.psMgr.tempWakeUp == 1)
{
frameCtrlMSB = zmw_rx_buf_readb(dev, buf, 1);
/* check more data */
if ( frameCtrlMSB & ZM_BIT_5 )
{
//if rx frame's AC is not delivery-enabled
if ((wd->sta.qosInfo&0xf) != 0xf)
{
u8_t rxAc = 0;
if ((frameSubtype & 0x80) != 0)
{
rxAc = zcUpToAc[zmw_buf_readb(dev, buf, 24)&0x7];
}
if (((0x8>>rxAc) & wd->sta.qosInfo) == 0)
{
zfSendPSPoll(dev);
wd->sta.psMgr.tempWakeUp = 0;
}
}
}
}
/*increase beacon count when receive vaild data frame from AP*/
ZM_MAC_WORD_TO_BYTE(wd->sta.bssid, bssid);
if (zfStaIsConnected(dev)&&
zfRxBufferEqualToStr(dev, buf, bssid, ZM_WLAN_HEADER_A2_OFFSET, 6))
{
wd->sta.rxBeaconCount++;
}
}
zm_msg1_rx(ZM_LV_2, "Rx VAP=", vap);
/* handle IV, EXT-IV, ICV, and EXT-ICV */
zfGetRxIvIcvLength(dev, buf, vap, &offset, &tailLen, addInfo);
zfStaIbssPSCheckState(dev, buf);
//QoS data frame
if ((frameSubtype & 0x80) == 0x80)
{
offset += 2;
}
len = zfwBufGetSize(dev, buf);
/* remove ICV */
if (tailLen > 0)
{
if (len > tailLen)
{
len -= tailLen;
zfwBufSetSize(dev, buf, len);
}
}
/* Filter NULL data */
if (((frameSubtype&0x40) != 0) || ((len = zfwBufGetSize(dev, buf))<=24))
{
zm_msg1_rx(ZM_LV_1, "Free Rx NULL data, len=", len);
zfwBufFree(dev, buf, 0);
return;
}
/* check and handle defragmentation */
if ( wd->sta.bSafeMode && (wd->sta.wepStatus == ZM_ENCRYPTION_AES) && wd->sta.SWEncryptEnable )
{
zm_msg0_rx(ZM_LV_1, "Bypass defragmentation packets in safe mode");
}
else
{
buf = zfDefragment(dev, buf, &bIsDefrag, addInfo);
if (buf == NULL)
{
/* In this case, the buffer has been freed in zfDefragment */
return;
}
}
ret = ZM_MIC_SUCCESS;
/* If SW WEP/TKIP are not turned on */
if ((wd->sta.SWEncryptEnable & ZM_SW_TKIP_DECRY_EN) == 0 &&
(wd->sta.SWEncryptEnable & ZM_SW_WEP_DECRY_EN) == 0)
{
encryMode = zfGetEncryModeFromRxStatus(addInfo);
/* check if TKIP */
if ( encryMode == ZM_TKIP )
{
if ( bIsDefrag )
{
ret = zfMicRxVerify(dev, buf);
}
else
{
/* check MIC failure bit */
if ( ZM_RX_STATUS_IS_MIC_FAIL(addInfo) )
{
ret = ZM_MIC_FAILURE;
}
}
if ( ret == ZM_MIC_FAILURE )
{
u8_t Unicast_Pkt = 0x0;
if ((zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET) & 0x1) == 0)
{
wd->commTally.swRxUnicastMicFailCount++;
Unicast_Pkt = 0x1;
}/*
else if (zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET) == 0xffff)
{
wd->commTally.swRxMulticastMicFailCount++;
}*/
else
{
wd->commTally.swRxMulticastMicFailCount++;
}
if ( wd->wlanMode == ZM_MODE_AP )
{
u16_t idx;
u8_t addr[6];
for (idx=0; idx<6; idx++)
{
addr[idx] = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+idx);
}
if (wd->zfcbApMicFailureNotify != NULL)
{
wd->zfcbApMicFailureNotify(dev, addr, buf);
}
}
else
{
if(Unicast_Pkt)
{
zm_debug_msg0("Countermeasure : Unicast_Pkt ");
}
else
{
zm_debug_msg0("Countermeasure : Non-Unicast_Pkt ");
}
if((wd->TKIP_Group_KeyChanging == 0x0) || (Unicast_Pkt == 0x1))
{
zm_debug_msg0("Countermeasure : Do MIC Check ");
zfStaMicFailureHandling(dev, buf);
}
else
{
zm_debug_msg0("Countermeasure : SKIP MIC Check due to Group Keychanging ");
}
}
/* Discard MIC failed frame */
zfwBufFree(dev, buf, 0);
return;
}
}
}
else
{
u8_t IsEncryFrame;
/* TODO: Check whether WEP bit is turned on in MAC header */
encryMode = ZM_NO_WEP;
IsEncryFrame = (zmw_rx_buf_readb(dev, buf, 1) & 0x40);
if (IsEncryFrame)
{
/* Software decryption for TKIP */
if (wd->sta.SWEncryptEnable & ZM_SW_TKIP_DECRY_EN)
{
u16_t iv16;
u16_t iv32;
u8_t RC4Key[16];
u16_t IvOffset;
struct zsTkipSeed *rxSeed;
IvOffset = offset + ZM_SIZE_OF_WLAN_DATA_HEADER;
rxSeed = zfStaGetRxSeed(dev, buf);
if (rxSeed == NULL)
{
zm_debug_msg0("rxSeed is NULL");
/* Discard this frame */
zfwBufFree(dev, buf, 0);
return;
}
iv16 = (zmw_rx_buf_readb(dev, buf, IvOffset) << 8) + zmw_rx_buf_readb(dev, buf, IvOffset+2);
iv32 = zmw_rx_buf_readb(dev, buf, IvOffset+4) +
(zmw_rx_buf_readb(dev, buf, IvOffset+5) << 8) +
(zmw_rx_buf_readb(dev, buf, IvOffset+6) << 16) +
(zmw_rx_buf_readb(dev, buf, IvOffset+7) << 24);
/* TKIP Key Mixing */
zfTkipPhase1KeyMix(iv32, rxSeed);
zfTkipPhase2KeyMix(iv16, rxSeed);
zfTkipGetseeds(iv16, RC4Key, rxSeed);
/* Decrypt Data */
ret = zfTKIPDecrypt(dev, buf, IvOffset+ZM_SIZE_OF_IV+ZM_SIZE_OF_EXT_IV, 16, RC4Key);
if (ret == ZM_ICV_FAILURE)
{
zm_debug_msg0("TKIP ICV fail");
/* Discard ICV failed frame */
zfwBufFree(dev, buf, 0);
return;
}
/* Remove ICV from buffer */
zfwBufSetSize(dev, buf, len-4);
/* Check MIC */
ret = zfMicRxVerify(dev, buf);
if (ret == ZM_MIC_FAILURE)
{
if ((zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET) & 0x1) == 0)
{
wd->commTally.swRxUnicastMicFailCount++;
}
else if (zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET) == 0xffff)
{
wd->commTally.swRxMulticastMicFailCount++;
}
else
{
wd->commTally.swRxMulticastMicFailCount++;
}
if ( wd->wlanMode == ZM_MODE_AP )
{
u16_t idx;
u8_t addr[6];
for (idx=0; idx<6; idx++)
{
addr[idx] = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+idx);
}
if (wd->zfcbApMicFailureNotify != NULL)
{
wd->zfcbApMicFailureNotify(dev, addr, buf);
}
}
else
{
zfStaMicFailureHandling(dev, buf);
}
zm_debug_msg0("MIC fail");
/* Discard MIC failed frame */
zfwBufFree(dev, buf, 0);
return;
}
encryMode = ZM_TKIP;
offset += ZM_SIZE_OF_IV + ZM_SIZE_OF_EXT_IV;
}
else if(wd->sta.SWEncryptEnable & ZM_SW_WEP_DECRY_EN)
{
u16_t IvOffset;
u8_t keyLen = 5;
u8_t iv[3];
u8_t keyIdx;
IvOffset = offset + ZM_SIZE_OF_WLAN_DATA_HEADER;
/* Retrieve IV */
iv[0] = zmw_rx_buf_readb(dev, buf, IvOffset);
iv[1] = zmw_rx_buf_readb(dev, buf, IvOffset+1);
iv[2] = zmw_rx_buf_readb(dev, buf, IvOffset+2);
keyIdx = ((zmw_rx_buf_readb(dev, buf, IvOffset+3) >> 6) & 0x03);
IvOffset += ZM_SIZE_OF_IV;
if (wd->sta.SWEncryMode[keyIdx] == ZM_WEP64)
{
keyLen = 5;
}
else if (wd->sta.SWEncryMode[keyIdx] == ZM_WEP128)
{
keyLen = 13;
}
else if (wd->sta.SWEncryMode[keyIdx] == ZM_WEP256)
{
keyLen = 29;
}
zfWEPDecrypt(dev, buf, IvOffset, keyLen, wd->sta.wepKey[keyIdx], iv);
if (ret == ZM_ICV_FAILURE)
{
zm_debug_msg0("WEP ICV fail");
/* Discard ICV failed frame */
zfwBufFree(dev, buf, 0);
return;
}
encryMode = wd->sta.SWEncryMode[keyIdx];
/* Remove ICV from buffer */
zfwBufSetSize(dev, buf, len-4);
offset += ZM_SIZE_OF_IV;
}
}
}
#ifdef ZM_ENABLE_CENC
//else if ( encryMode == ZM_CENC ) /* check if CENC */
if ( encryMode == ZM_CENC )
{
u32_t rxIV[4];
rxIV[0] = (zmw_rx_buf_readh(dev, buf, 28) << 16)
+ zmw_rx_buf_readh(dev, buf, 26);
rxIV[1] = (zmw_rx_buf_readh(dev, buf, 32) << 16)
+ zmw_rx_buf_readh(dev, buf, 30);
rxIV[2] = (zmw_rx_buf_readh(dev, buf, 36) << 16)
+ zmw_rx_buf_readh(dev, buf, 34);
rxIV[3] = (zmw_rx_buf_readh(dev, buf, 40) << 16)
+ zmw_rx_buf_readh(dev, buf, 38);
//zm_debug_msg2("rxIV[0] = 0x", rxIV[0]);
//zm_debug_msg2("rxIV[1] = 0x", rxIV[1]);
//zm_debug_msg2("rxIV[2] = 0x", rxIV[2]);
//zm_debug_msg2("rxIV[3] = 0x", rxIV[3]);
/* destination address*/
da[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET);
da[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET+2);
da[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET+4);
if ( wd->wlanMode == ZM_MODE_AP )
{
}
else
{
if ((da[0] & 0x1))
{ //multicast frame
/* Accumlate the PN sequence */
wd->sta.rxivGK[0] ++;
if (wd->sta.rxivGK[0] == 0)
{
wd->sta.rxivGK[1]++;
}
if (wd->sta.rxivGK[1] == 0)
{
wd->sta.rxivGK[2]++;
}
if (wd->sta.rxivGK[2] == 0)
{
wd->sta.rxivGK[3]++;
}
if (wd->sta.rxivGK[3] == 0)
{
wd->sta.rxivGK[0] = 0;
wd->sta.rxivGK[1] = 0;
wd->sta.rxivGK[2] = 0;
}
//zm_debug_msg2("wd->sta.rxivGK[0] = 0x", wd->sta.rxivGK[0]);
//zm_debug_msg2("wd->sta.rxivGK[1] = 0x", wd->sta.rxivGK[1]);
//zm_debug_msg2("wd->sta.rxivGK[2] = 0x", wd->sta.rxivGK[2]);
//zm_debug_msg2("wd->sta.rxivGK[3] = 0x", wd->sta.rxivGK[3]);
if ( !((wd->sta.rxivGK[0] == rxIV[0])
&& (wd->sta.rxivGK[1] == rxIV[1])
&& (wd->sta.rxivGK[2] == rxIV[2])
&& (wd->sta.rxivGK[3] == rxIV[3])))
{
u8_t PacketDiscard = 0;
/* Discard PN Code Error frame */
if (rxIV[0] < wd->sta.rxivGK[0])
{
PacketDiscard = 1;
}
if (wd->sta.rxivGK[0] > 0xfffffff0)
{ //boundary case
if ((rxIV[0] < 0xfffffff0)
&& (((0xffffffff - wd->sta.rxivGK[0]) + rxIV[0]) > 16))
{
PacketDiscard = 1;
}
}
else
{ //normal case
if ((rxIV[0] - wd->sta.rxivGK[0]) > 16)
{
PacketDiscard = 1;
}
}
// sync sta pn code with ap because of losting some packets
wd->sta.rxivGK[0] = rxIV[0];
wd->sta.rxivGK[1] = rxIV[1];
wd->sta.rxivGK[2] = rxIV[2];
wd->sta.rxivGK[3] = rxIV[3];
if (PacketDiscard)
{
zm_debug_msg0("Discard PN Code lost too much multicast frame");
zfwBufFree(dev, buf, 0);
return;
}
}
}
else
{ //unicast frame
/* Accumlate the PN sequence */
wd->sta.rxiv[0] += 2;
if (wd->sta.rxiv[0] == 0 || wd->sta.rxiv[0] == 1)
{
wd->sta.rxiv[1]++;
}
if (wd->sta.rxiv[1] == 0)
{
wd->sta.rxiv[2]++;
}
if (wd->sta.rxiv[2] == 0)
{
wd->sta.rxiv[3]++;
}
if (wd->sta.rxiv[3] == 0)
{
wd->sta.rxiv[0] = 0;
wd->sta.rxiv[1] = 0;
wd->sta.rxiv[2] = 0;
}
//zm_debug_msg2("wd->sta.rxiv[0] = 0x", wd->sta.rxiv[0]);
//zm_debug_msg2("wd->sta.rxiv[1] = 0x", wd->sta.rxiv[1]);
//zm_debug_msg2("wd->sta.rxiv[2] = 0x", wd->sta.rxiv[2]);
//zm_debug_msg2("wd->sta.rxiv[3] = 0x", wd->sta.rxiv[3]);
if ( !((wd->sta.rxiv[0] == rxIV[0])
&& (wd->sta.rxiv[1] == rxIV[1])
&& (wd->sta.rxiv[2] == rxIV[2])
&& (wd->sta.rxiv[3] == rxIV[3])))
{
zm_debug_msg0("PN Code mismatch, lost unicast frame, sync pn code to recv packet");
// sync sta pn code with ap because of losting some packets
wd->sta.rxiv[0] = rxIV[0];
wd->sta.rxiv[1] = rxIV[1];
wd->sta.rxiv[2] = rxIV[2];
wd->sta.rxiv[3] = rxIV[3];
/* Discard PN Code Error frame */
//zm_debug_msg0("Discard PN Code mismatch unicast frame");
//zfwBufFree(dev, buf, 0);
//return;
}
}
}
}
#endif //ZM_ENABLE_CENC
/* for tally */
if ((zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET) & 0x1) == 0)
{
/* for ACU to display RxRate */
zfWlanUpdateRxRate(dev, addInfo);
wd->commTally.rxUnicastFrm++;
wd->commTally.rxUnicastOctets += (len-24);
}
else if (zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET) == 0xffff)
{
wd->commTally.rxBroadcastFrm++;
wd->commTally.rxBroadcastOctets += (len-24);
}
else
{
wd->commTally.rxMulticastFrm++;
wd->commTally.rxMulticastOctets += (len-24);
}
wd->ledStruct.rxTraffic++;
if ((frameSubtype & 0x80) == 0x80)
{
/* if QoS control bit-7 is 1 => A-MSDU frame */
if ((zmw_rx_buf_readh(dev, buf, 24) & 0x80) != 0)
{
zfDeAmsdu(dev, buf, vap, encryMode);
return;
}
}
// Remove MIC of TKIP
if ( encryMode == ZM_TKIP )
{
zfwBufSetSize(dev, buf, zfwBufGetSize(dev, buf) - 8);
}
/* Convert 802.11 and SNAP header to ethernet header */
if ( (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)||
(wd->wlanMode == ZM_MODE_IBSS) )
{
/* destination address*/
da[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET);
da[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET+2);
da[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET+4);
/* check broadcast frame */
if ( (da[0] == 0xffff) && (da[1] == 0xffff) && (da[2] == 0xffff) )
{
// Ap send broadcast frame to the DUT !
}
/* check multicast frame */
/* TODO : Remove these code, hardware should be able to block */
/* multicast frame on the multicast address list */
/* or bypass all multicast packet by flag bAllMulticast */
else if ((da[0] & 0x01) && (wd->sta.bAllMulticast == 0))
{
for(ii=0; ii<wd->sta.multicastList.size; ii++)
{
if ( zfMemoryIsEqual(wd->sta.multicastList.macAddr[ii].addr,
(u8_t*) da, 6))
{
break;
}
}
if ( ii == wd->sta.multicastList.size )
{ /* not found */
zm_debug_msg0("discard unknown multicast frame");
zfwBufFree(dev, buf, 0);
return;
}
}
#ifdef ZM_ENABLE_NATIVE_WIFI //Native Wifi : 1, Ethernet format : 0
//To remove IV
if (offset > 0)
{
for (i=12; i>0; i--)
{
zmw_rx_buf_writeh(dev, buf, ((i-1)*2)+offset,
zmw_rx_buf_readh(dev, buf, (i-1)*2));
}
zfwBufRemoveHead(dev, buf, offset);
}
#else
if (zfRxBufferEqualToStr(dev, buf, zgSnapBridgeTunnel,
24+offset, 6))
{
snapCase = 1;
}
else if ( zfRxBufferEqualToStr(dev, buf, zgSnap8021h,
24+offset, 6) )
{
typeLengthField =
(((u16_t) zmw_rx_buf_readb(dev, buf, 30+offset)) << 8) +
zmw_rx_buf_readb(dev, buf, 31+offset);
//zm_debug_msg2("tpyeLengthField = ", typeLengthField);
//8137 : IPX, 80F3 : Appletalk
if ( (typeLengthField != 0x8137)&&
(typeLengthField != 0x80F3) )
{
snapCase = 2;
}
if ( typeLengthField == 0x888E )
{
zfShowRxEAPOL(dev, buf, 32);
}
}
else
{
//zfwDumpBuf(dev, buf);
}
/* source address */
if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
{
/* SA = Address 3 */
sa[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET);
sa[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+2);
sa[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+4);
}
else
{
/* SA = Address 2 */
sa[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET);
sa[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+2);
sa[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+4);
}
if ( snapCase )
{
/* SA */
zmw_rx_buf_writeh(dev, buf, 24+offset, sa[0]);
zmw_rx_buf_writeh(dev, buf, 26+offset, sa[1]);
zmw_rx_buf_writeh(dev, buf, 28+offset, sa[2]);
/* DA = Address 1 */
zmw_rx_buf_writeh(dev, buf, 18+offset, da[0]);
zmw_rx_buf_writeh(dev, buf, 20+offset, da[1]);
zmw_rx_buf_writeh(dev, buf, 22+offset, da[2]);
zfwBufRemoveHead(dev, buf, 18+offset);
}
else
{
/* SA */
zmw_rx_buf_writeh(dev, buf, 16+offset, sa[0]);
zmw_rx_buf_writeh(dev, buf, 18+offset, sa[1]);
zmw_rx_buf_writeh(dev, buf, 20+offset, sa[2]);
/* DA = Address 1 */
zmw_rx_buf_writeh(dev, buf, 10+offset, da[0]);
zmw_rx_buf_writeh(dev, buf, 12+offset, da[1]);
zmw_rx_buf_writeh(dev, buf, 14+offset, da[2]);
zfwBufRemoveHead(dev, buf, 10+offset);
/* Ethernet payload length */
typeLengthField = zfwBufGetSize(dev, buf) - 14;
zmw_rx_buf_writeh(dev, buf, 12, (typeLengthField<<8)+(typeLengthField>>8));
}
#endif // ZM_ENABLE_NATIVE_WIFI
}
else if (wd->wlanMode == ZM_MODE_AP)
{
//if ((zmw_rx_buf_readb(dev, buf, 1) & 0x3) != 3)
if (vap < ZM_MAX_AP_SUPPORT)
/* AP mode */
{
#ifdef ZM_ENABLE_NATIVE_WIFI //Native Wifi : 1, Ethernet format : 0
//To remove IV
if (offset > 0)
{
for (i=12; i>0; i--)
{
zmw_rx_buf_writeh(dev, buf, ((i-1)*2)+offset,
zmw_rx_buf_readh(dev, buf, (i-1)*2));
}
zfwBufRemoveHead(dev, buf, offset);
}
#else
/* SA = Address 2 */
zmw_rx_buf_writeh(dev, buf, 24+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A2_OFFSET));
zmw_rx_buf_writeh(dev, buf, 26+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A2_OFFSET+2));
zmw_rx_buf_writeh(dev, buf, 28+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A2_OFFSET+4));
/* DA = Address 3 */
/* Seq : Read 20 write 22, read 18 write 20, read 16 write 18 */
/* sequence must not be inverted */
zmw_rx_buf_writeh(dev, buf, 22+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A3_OFFSET+4));
zmw_rx_buf_writeh(dev, buf, 20+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A3_OFFSET+2));
zmw_rx_buf_writeh(dev, buf, 18+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A3_OFFSET));
zfwBufRemoveHead(dev, buf, 18+offset);
#endif // ZM_ENABLE_NATIVE_WIFI
#if 1
ret = zfIntrabssForward(dev, buf, vap);
if (ret == 1)
{
/* Free Rx buffer if intra-BSS unicast frame */
zm_msg0_rx(ZM_LV_2, "Free intra-BSS unicast frame");
zfwBufFree(dev, buf, 0);
return;
}
#endif
}
else
/* WDS mode */
{
zm_msg0_rx(ZM_LV_2, "Rx WDS data");
/* SA = Address 4 */
zmw_rx_buf_writeh(dev, buf, 30+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A4_OFFSET));
zmw_rx_buf_writeh(dev, buf, 32+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A4_OFFSET+2));
zmw_rx_buf_writeh(dev, buf, 34+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A4_OFFSET+4));
/* DA = Address 3 */
/* Seq : Read 20 write 22, read 18 write 20, read 16 write 18 */
/* sequence must not be inverted */
zmw_rx_buf_writeh(dev, buf, 28+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A3_OFFSET+4));
zmw_rx_buf_writeh(dev, buf, 26+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A3_OFFSET+2));
zmw_rx_buf_writeh(dev, buf, 24+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A3_OFFSET));
zfwBufRemoveHead(dev, buf, 24+offset);
}
}
else if (wd->wlanMode == ZM_MODE_PSEUDO)
{
/* WDS test: remove add4 */
if (wd->enableWDS)
{
offset += 6;
}
/* SA = Address 2 */
zmw_rx_buf_writeh(dev, buf, 24+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A2_OFFSET));
zmw_rx_buf_writeh(dev, buf, 26+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A2_OFFSET+2));
zmw_rx_buf_writeh(dev, buf, 28+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A2_OFFSET+4));
/* DA = Address 1 */
zmw_rx_buf_writeh(dev, buf, 18+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A1_OFFSET));
zmw_rx_buf_writeh(dev, buf, 20+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A1_OFFSET+2));
zmw_rx_buf_writeh(dev, buf, 22+offset, zmw_rx_buf_readh(dev, buf,
ZM_WLAN_HEADER_A1_OFFSET+4));
zfwBufRemoveHead(dev, buf, 18+offset);
}
else
{
zm_assert(0);
}
/* Call zfwRecvEth() to notify upper layer */
//zm_msg2_rx(ZM_LV_2, "Call zfwRecvEth(), buf=", buf);
//zfwDumpBuf(dev, buf);
#if ZM_PROTOCOL_RESPONSE_SIMULATION == 1
zfProtRspSim(dev, buf);
#endif
//zfwDumpBuf(dev, buf);
/* tally */
wd->commTally.NotifyNDISRxFrmCnt++;
if (wd->zfcbRecvEth != NULL)
{
wd->zfcbRecvEth(dev, buf, vap);
ZM_PERFORMANCE_RX_MSDU(dev, wd->tick)
}
}
/* if management frame */
else if (frameType == ZM_WLAN_MANAGEMENT_FRAME)
{
zm_msg2_rx(ZM_LV_2, "Rx management,FC=", frameCtrl);
/* Call zfProcessManagement() to handle management frame */
zfProcessManagement(dev, buf, addInfo); //CWYang(m)
zfwBufFree(dev, buf, 0);
}
/* PsPoll */
else if ((wd->wlanMode == ZM_MODE_AP) && (frameCtrl == 0xa4))
{
zm_msg0_rx(ZM_LV_0, "Rx PsPoll");
zfApProcessPsPoll(dev, buf);
zfwBufFree(dev, buf, 0);
}
else
{
zm_msg0_rx(ZM_LV_1, "Rx discard!!");
wd->commTally.DriverDiscardedFrm++;
zfwBufFree(dev, buf, 0);
}
return;
}
Generated by GNU enscript 1.6.4.