aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/otus/80211core/cic.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/otus/80211core/cic.c')
-rw-r--r--drivers/staging/otus/80211core/cic.c496
1 files changed, 496 insertions, 0 deletions
diff --git a/drivers/staging/otus/80211core/cic.c b/drivers/staging/otus/80211core/cic.c
new file mode 100644
index 000000000000..c84f079e3d84
--- /dev/null
+++ b/drivers/staging/otus/80211core/cic.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "cprecomp.h"
+#include "ratectrl.h"
+
+
+void zfUpdateBssid(zdev_t* dev, u8_t* bssid)
+{
+
+ zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+ //zmw_enter_critical_section(dev);
+ wd->sta.bssid[0] = bssid[0] + (((u16_t) bssid[1]) << 8);
+ wd->sta.bssid[1] = bssid[2] + (((u16_t) bssid[3]) << 8);
+ wd->sta.bssid[2] = bssid[4] + (((u16_t) bssid[5]) << 8);
+ //zmw_leave_critical_section(dev);
+
+ zfHpSetBssid(dev, bssid);
+
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfResetSupportRate */
+/* Reset support rate to default value. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* type: ZM_DEFAULT_SUPPORT_RATE_ZERO => reset to zero */
+/* ZM_DEFAULT_SUPPORT_RATE_DISCONNECT => reset to disconnect status */
+/* ZM_DEFAULT_SUPPORT_RATE_IBSS_B => reset to IBSS creator(b mode) */
+/* ZM_DEFAULT_SUPPORT_RATE_IBSS_AG => reset to IBSS creator(a/g mode) */
+/* */
+/************************************************************************************/
+void zfResetSupportRate(zdev_t* dev, u8_t type)
+{
+ zmw_get_wlan_dev(dev);
+
+ switch(type)
+ {
+ case ZM_DEFAULT_SUPPORT_RATE_ZERO:
+ wd->bRate = 0;
+ wd->bRateBasic = 0;
+ wd->gRate = 0;
+ wd->gRateBasic = 0;
+ break;
+ case ZM_DEFAULT_SUPPORT_RATE_DISCONNECT:
+ wd->bRate = 0xf;
+ wd->bRateBasic = 0xf;
+ wd->gRate = 0xff;
+ wd->gRateBasic = 0x15;
+ break;
+ case ZM_DEFAULT_SUPPORT_RATE_IBSS_B:
+ wd->bRate = 0xf;
+ wd->bRateBasic = 0xf;
+ wd->gRate = 0;
+ wd->gRateBasic = 0;
+ break;
+ case ZM_DEFAULT_SUPPORT_RATE_IBSS_AG:
+ wd->bRate = 0xf;
+ wd->bRateBasic = 0xf;
+ wd->gRate = 0xff;
+ wd->gRateBasic = 0;
+ break;
+ }
+}
+
+void zfUpdateSupportRate(zdev_t* dev, u8_t* rateArray)
+{
+ u8_t bRate=0, bRateBasic=0, gRate=0, gRateBasic=0;
+ u8_t length = rateArray[1];
+ u8_t i, j;
+
+ zmw_get_wlan_dev(dev);
+
+ for(i=2; i<length+2; i++)
+ {
+ for(j=0; j<4; j++)
+ {
+ if ( (rateArray[i] & 0x7f) == zg11bRateTbl[j] )
+ {
+ bRate |= (1 << j);
+ if ( rateArray[i] & 0x80 )
+ {
+ bRateBasic |= (1 << j);
+ }
+ }
+ }
+
+ if ( j == 4 )
+ {
+ for(j=0; j<8; j++)
+ {
+ if ( (rateArray[i] & 0x7f) == zg11gRateTbl[j] )
+ {
+ gRate |= (1 << j);
+ if ( rateArray[i] & 0x80 )
+ {
+ gRateBasic |= (1 << j);
+ }
+ }
+ }
+ }
+ }
+
+
+ wd->bRate |= bRate;
+ wd->bRateBasic |= bRateBasic;
+ wd->gRate |= gRate;
+ wd->gRateBasic |= gRateBasic;
+}
+
+u8_t zfIsGOnlyMode(zdev_t* dev, u16_t frequency, u8_t* rateArray)
+{
+ u8_t length = rateArray[1];
+ u8_t i, j;
+
+ if (frequency < 3000) {
+ for (i = 2; i < length+2; i++) {
+ for (j = 0; j < 8; j++) {
+ if ( ((rateArray[i] & 0x7f) == zg11gRateTbl[j])
+ && (rateArray[i] & 0x80) ) {
+ return 1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+void zfGatherBMode(zdev_t* dev, u8_t* rateArray, u8_t* extrateArray)
+{
+ u8_t gatherBMode[ZM_MAX_SUPP_RATES_IE_SIZE + 2];
+ u8_t i, j, k = 0;
+ u8_t length;
+
+ gatherBMode[0] = ZM_WLAN_EID_SUPPORT_RATE;
+ gatherBMode[1] = 0;
+
+ length = rateArray[1];
+ for (i = 2; i < length+2; i++) {
+ for (j = 0; j < 4; j++) {
+ if ( (rateArray[i] & 0x7f) == zg11bRateTbl[j] ) {
+ gatherBMode[2+k] = rateArray[i];
+
+ gatherBMode[1]++;
+ k++;
+ }
+ }
+ }
+
+ length = extrateArray[1];
+ for (i = 2; i < length+2; i++) {
+ for (j = 0; j < 4; j++) {
+ if ( (extrateArray[i] & 0x7f) == zg11bRateTbl[j] ) {
+ gatherBMode[2+k] = extrateArray[i];
+
+ gatherBMode[1]++;
+ k++;
+ }
+ }
+ }
+
+ extrateArray[0] = extrateArray[1] = 0;
+ zfMemoryCopy(rateArray, gatherBMode, gatherBMode[1]+2);
+}
+
+u16_t zfGetRandomNumber(zdev_t* dev, u16_t initValue)
+{
+#if 0
+ /* Compiler/Linker error on Linux */
+ if ( initValue )
+ {
+ srand(initValue);
+ }
+
+ return ((u16_t)rand());
+#endif
+ return 0;
+}
+
+u8_t zfPSDeviceSleep(zdev_t* dev)
+{
+ //zmw_get_wlan_dev(dev);
+
+ /* enter PS mode */
+
+ return 0;
+}
+
+u8_t zcOfdmPhyCrtlToRate[] =
+{
+ /* 0x8=48M, 0x9=24M, 0xa=12M, 0xb=6M, 0xc=54M, 0xd=36M, 0xe=18M, 0xf=9M */
+ 10, 8, 6, 4, 11, 9, 7, 5
+};
+
+u8_t zfPhyCtrlToRate(u32_t phyCtrl)
+{
+ u32_t mt, mcs, sg;
+ u8_t rate = 0;
+
+ mt = phyCtrl & 0x3;
+ mcs = (phyCtrl>>18) & 0x3f;
+ sg = (phyCtrl>>31) & 0x1;
+
+ if ((mt == 0) && (mcs <=3))
+ {
+ rate = (u8_t)mcs;
+ }
+ else if ((mt == 1) && (mcs >= 0x8) && (mcs <= 0xf))
+ {
+ rate = zcOfdmPhyCrtlToRate[mcs-8];
+ }
+ else if ((mt == 2) && (mcs <= 15))
+ {
+ rate = (u8_t)mcs + 12;
+ if(sg) {
+ if (mcs != 7)
+ {
+ rate = (u8_t)mcs + 12 + 2;
+ }
+ else //MCS7-SG
+ {
+ rate = (u8_t)30;
+ }
+ }
+ }
+
+ return rate;
+}
+
+
+void zfCoreEvent(zdev_t* dev, u16_t event, u8_t* rsp)
+{
+ u16_t i;
+ zbuf_t* psBuf;
+ u8_t moreData;
+ u8_t vap = 0;
+ u8_t peerIdx;
+ s8_t res;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+
+ if (event == 0) //Beacon Event
+ {
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ zfApSendBeacon(dev);
+
+ if (wd->CurrentDtimCount == 0)
+ {
+ /* TODO : Send queued broadcast frames at BC/MC event */
+ do
+ {
+ psBuf = NULL;
+ moreData = 0;
+ zmw_enter_critical_section(dev);
+ if (wd->ap.bcmcTail[vap] != wd->ap.bcmcHead[vap])
+ {
+ //zm_msg0_mm(ZM_LV_0, "Send BCMC frames");
+ psBuf = wd->ap.bcmcArray[vap][wd->ap.bcmcHead[vap]];
+ wd->ap.bcmcHead[vap] = (wd->ap.bcmcHead[vap] + 1)
+ & (ZM_BCMC_ARRAY_SIZE - 1);
+ if (wd->ap.bcmcTail[vap] != wd->ap.bcmcHead[vap])
+ {
+ moreData = 0x20;
+ }
+ }
+ zmw_leave_critical_section(dev);
+ if (psBuf != NULL)
+ {
+ /* TODO : config moreData bit */
+ zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF,
+ moreData);
+ }
+ } while(psBuf != NULL);
+
+ }
+ }
+ else
+ {
+ /* STA mode */
+ if ( wd->sta.powerSaveMode > ZM_STA_PS_NONE )
+ {
+ /* send queued packets */
+ for(i=0; i<wd->sta.staPSDataCount; i++)
+ {
+ zfTxSendEth(dev, wd->sta.staPSDataQueue[i], 0,
+ ZM_EXTERNAL_ALLOC_BUF, 0);
+ }
+
+ wd->sta.staPSDataCount = 0;
+ }
+
+ if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ zfStaSendBeacon(dev);
+ wd->sta.ibssAtimTimer = ZM_BIT_15 | wd->sta.atimWindow;
+ }
+
+ zfPowerSavingMgrPreTBTTInterrupt(dev);
+ }
+ } //if (event == 0) //Beacon Event
+ else if (event == 1) //Retry completed event
+ {
+ u32_t retryRate;
+
+ retryRate = (u32_t)(rsp[6]) + (((u32_t)(rsp[7]))<<8)
+ + (((u32_t)(rsp[8]))<<16) + (((u32_t)(rsp[9]))<<24);
+ /* Degrade Tx Rate */
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ zmw_enter_critical_section(dev);
+ if ((i=zfApFindSta(dev, (u16_t*)rsp)) != 0xffff)
+ {
+ zfRateCtrlTxFailEvent(dev, &wd->ap.staTable[i].rcCell, 0,(u32_t)zfPhyCtrlToRate(retryRate));
+ }
+ zmw_leave_critical_section(dev);
+ }
+ else
+ {
+ zmw_enter_critical_section(dev);
+ res = zfStaFindOppositeByMACAddr(dev, (u16_t*)rsp, &peerIdx);
+ if ( res == 0 )
+ {
+ zfRateCtrlTxFailEvent(dev, &wd->sta.oppositeInfo[peerIdx].rcCell, 0,(u32_t)zfPhyCtrlToRate(retryRate));
+ }
+ zmw_leave_critical_section(dev);
+ }
+ } //else if (event == 1) //Retry completed event
+ else if (event == 2) //Tx Fail event
+ {
+ u32_t retryRate;
+
+ retryRate = (u32_t)(rsp[6]) + (((u32_t)(rsp[7]))<<8)
+ + (((u32_t)(rsp[8]))<<16) + (((u32_t)(rsp[9]))<<24);
+
+ /* Degrade Tx Rate */
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ zmw_enter_critical_section(dev);
+ if ((i=zfApFindSta(dev, (u16_t*)rsp)) != 0xffff)
+ {
+ zfRateCtrlTxFailEvent(dev, &wd->ap.staTable[i].rcCell, 0,(u32_t)zfPhyCtrlToRate(retryRate));
+ }
+ zmw_leave_critical_section(dev);
+
+ zfApSendFailure(dev, rsp);
+ }
+ else
+ {
+ zmw_enter_critical_section(dev);
+ res = zfStaFindOppositeByMACAddr(dev, (u16_t*)rsp, &peerIdx);
+ if ( res == 0 )
+ {
+ zfRateCtrlTxFailEvent(dev, &wd->sta.oppositeInfo[peerIdx].rcCell, 0,(u32_t)zfPhyCtrlToRate(retryRate));
+ }
+ zmw_leave_critical_section(dev);
+ }
+ } //else if (event == 2) //Tx Fail event
+ else if (event == 3) //Tx Comp event
+ {
+ u32_t retryRate;
+
+ retryRate = (u32_t)(rsp[6]) + (((u32_t)(rsp[7]))<<8)
+ + (((u32_t)(rsp[8]))<<16) + (((u32_t)(rsp[9]))<<24);
+
+ /* TODO : Tx completed, used for rate control probing */
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ zmw_enter_critical_section(dev);
+ if ((i=zfApFindSta(dev, (u16_t*)rsp)) != 0xffff)
+ {
+ zfRateCtrlTxSuccessEvent(dev, &wd->ap.staTable[i].rcCell, zfPhyCtrlToRate(retryRate));
+ }
+ zmw_leave_critical_section(dev);
+ }
+ else
+ {
+ zmw_enter_critical_section(dev);
+ res = zfStaFindOppositeByMACAddr(dev, (u16_t*)rsp, &peerIdx);
+ if ( res == 0 )
+ {
+ zfRateCtrlTxSuccessEvent(dev, &wd->sta.oppositeInfo[peerIdx].rcCell, zfPhyCtrlToRate(retryRate));
+ }
+ zmw_leave_critical_section(dev);
+ }
+ } //else if (event == 3) //Tx Comp event
+ else if (event == 4) //BA failed count
+ {
+ u32_t fail;
+ u32_t rate;
+ peerIdx = 0;
+
+ fail=((u32_t*)rsp)[0] & 0xFFFF;
+ rate=((u32_t*)rsp)[0] >> 16;
+
+ if (rate > 15) {
+ rate = (rate & 0xF) + 12 + 2;
+ }
+ else {
+ rate = rate + 12;
+ }
+
+ zmw_enter_critical_section(dev);
+ zfRateCtrlTxFailEvent(dev, &wd->sta.oppositeInfo[peerIdx].rcCell, (u8_t)rate, fail);
+ zmw_leave_critical_section(dev);
+ }
+}
+
+void zfBeaconCfgInterrupt(zdev_t* dev, u8_t* rsp)
+{
+ u32_t txBeaconCounter;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ txBeaconCounter = *((u32_t *)rsp);
+ if ( wd->sta.beaconTxCnt != txBeaconCounter )
+ {
+ wd->sta.txBeaconInd = 1;
+
+ zmw_enter_critical_section(dev);
+ wd->tickIbssSendBeacon = 0;
+ zmw_leave_critical_section(dev);
+ }
+ else
+ {
+ wd->sta.txBeaconInd = 0;
+ }
+
+#ifdef ZM_ENABLE_IBSS_DELAYED_JOIN_INDICATION
+ if ( wd->sta.txBeaconInd && wd->sta.ibssDelayedInd )
+ {
+ if (wd->zfcbIbssPartnerNotify != NULL)
+ {
+ wd->zfcbIbssPartnerNotify(dev, 1, &wd->sta.ibssDelayedIndEvent);
+ }
+
+ wd->sta.ibssDelayedInd = 0;
+ }
+#endif
+
+ wd->sta.beaconTxCnt = txBeaconCounter;
+
+ // Need to check if the time is expired after ATIM window??
+
+ // Check if we have buffered any data for those stations that are sleeping
+ // If it's true, then transmitting ATIM pkt to notify them
+
+#ifdef ZM_ENABLE_IBSS_PS
+ // TODO: Need to check if the station receive our ATIM pkt???
+ zfStaIbssPSSend(dev);
+
+ if ( wd->sta.atimWindow == 0 )
+ {
+ // We won't receive the end of ATIM isr so we fake it
+ zfPowerSavingMgrAtimWinExpired(dev);
+ }
+#endif
+ }
+}
+
+void zfEndOfAtimWindowInterrupt(zdev_t* dev)
+{
+#ifdef ZM_ENABLE_IBSS_PS
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ // Transmit any queued pkt for the stations!!
+ zfPowerSavingMgrAtimWinExpired(dev);
+ }
+#endif
+}