diff options
Diffstat (limited to 'drivers/staging/otus/80211core/cic.c')
-rw-r--r-- | drivers/staging/otus/80211core/cic.c | 496 |
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 00000000000..c84f079e3d8 --- /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 +} |