/* *************************************************************************** * Ralink Tech Inc. * 4F, No. 2 Technology 5th Rd. * Science-based Industrial Park * Hsin-chu, Taiwan, R.O.C. * * (c) Copyright 2002-2012, Ralink Technology, Inc. * * All rights reserved. Ralink's source code is an unpublished work and the * use of a copyright notice does not imply otherwise. This source code * contains confidential trade secret material of Ralink Tech. Any attemp * or participation in deciphering, decoding, reverse engineering or in any * way altering the source code is stricitly prohibited, unless the prior * written consent of Ralink Technology, Inc. is obtained. *************************************************************************** Module Name: ap_repeater.c Abstract: Support MAC Repeater function. Revision History: Who When What -------------- ---------- ---------------------------------------------- Arvin 11-16-2012 created */ #ifdef MAC_REPEATER_SUPPORT #include "rt_config.h" REPEATER_CLIENT_ENTRY *RTMPLookupRepeaterCliEntry( IN PRTMP_ADAPTER pAd, IN BOOLEAN bRealMAC, IN PUCHAR pAddr) { ULONG HashIdx; UCHAR tempMAC[6]; REPEATER_CLIENT_ENTRY *pEntry = NULL; REPEATER_CLIENT_ENTRY_MAP *pMapEntry = NULL; NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); COPY_MAC_ADDR(tempMAC, pAddr); HashIdx = MAC_ADDR_HASH_INDEX(tempMAC); if (bRealMAC == TRUE) { pMapEntry = pAd->ApCfg.ReptMapHash[HashIdx]; while (pMapEntry) { pEntry = pMapEntry->pReptCliEntry; if (pEntry->CliValid && MAC_ADDR_EQUAL(pEntry->OriginalAddress, tempMAC)) break; else { pEntry = NULL; pMapEntry = pMapEntry->pNext; } } } else { pEntry = pAd->ApCfg.ReptCliHash[HashIdx]; while (pEntry) { if (pEntry->CliValid && MAC_ADDR_EQUAL(pEntry->CurrentAddress, tempMAC)) break; else pEntry = pEntry->pNext; } } NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); return pEntry; } #if 0 VOID RTMPInsertRepeaterAsicEntry( IN PRTMP_ADAPTER pAd, IN UCHAR CliIdx, IN PUCHAR pAddr) { ULONG offset, Addr; UCHAR tempMAC[MAC_ADDR_LEN]; DBGPRINT(RT_DEBUG_WARN, (" %s.\n", __FUNCTION__)); COPY_MAC_ADDR(tempMAC, pAddr); offset = 0x1480 + (HW_WCID_ENTRY_SIZE * CliIdx); Addr = tempMAC[0] + (tempMAC[1] << 8) +(tempMAC[2] << 16) +(tempMAC[3] << 24); RTMP_IO_WRITE32(pAd, offset, Addr); Addr = tempMAC[4] + (tempMAC[5] << 8); RTMP_IO_WRITE32(pAd, offset + 4, Addr); DBGPRINT(RT_DEBUG_ERROR, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x\n", PRINT_MAC(tempMAC), CliIdx)); } VOID RTMPRemoveRepeaterAsicEntry( IN PRTMP_ADAPTER pAd, IN UCHAR CliIdx) { ULONG offset, Addr; DBGPRINT(RT_DEBUG_WARN, (" %s.\n", __FUNCTION__)); offset = 0x1480 + (HW_WCID_ENTRY_SIZE * CliIdx); Addr = 0; RTMP_IO_WRITE32(pAd, offset, Addr); RTMP_IO_WRITE32(pAd, offset + 4, Addr); } #endif VOID RTMPInsertRepeaterEntry( IN PRTMP_ADAPTER pAd, IN UCHAR apidx, IN PUCHAR pAddr) { INT CliIdx, idx; UCHAR HashIdx; BOOLEAN Cancelled; UCHAR tempMAC[MAC_ADDR_LEN]; APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; PREPEATER_CLIENT_ENTRY pReptCliEntry = NULL, pCurrEntry = NULL; PREPEATER_CLIENT_ENTRY_MAP pReptCliMap; UCHAR SPEC_ADDR[6][3] = {{0x02, 0x0F, 0xB5}, {0x02, 0x09, 0x5B}, {0x02, 0x14, 0x6C}, {0x02, 0x18, 0x4D}, {0x02, 0x1B, 0x2F}, {0x02, 0x1E, 0x2A}}; DBGPRINT(RT_DEBUG_TRACE, (" %s.\n", __FUNCTION__)); NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); if (pAd->ApCfg.RepeaterCliSize >= MAX_EXT_MAC_ADDR_SIZE) { DBGPRINT(RT_DEBUG_ERROR, (" Repeater Client Full !!!\n")); NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); return ; } if (pAd->ApCfg.ApCliTab[apidx].Enable == FALSE) { DBGPRINT(RT_DEBUG_ERROR, (" ApCli Interface is Down !!!\n")); NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); return ; } for (CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) { pReptCliEntry = &pAd->ApCfg.ApCliTab[apidx].RepeaterCli[CliIdx]; if ((pReptCliEntry->CliEnable) && (MAC_ADDR_EQUAL(pReptCliEntry->OriginalAddress, pAddr) || MAC_ADDR_EQUAL(pReptCliEntry->CurrentAddress, pAddr))) { DBGPRINT(RT_DEBUG_ERROR, ("\n receive mac :%02x:%02x:%02x:%02x:%02x:%02x !!!\n", pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5])); DBGPRINT(RT_DEBUG_ERROR, (" duplicate Insert !!!\n")); NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); return ; } if (pReptCliEntry->CliEnable == FALSE) break; } if (CliIdx >= MAX_EXT_MAC_ADDR_SIZE) { DBGPRINT(RT_DEBUG_ERROR, (" Repeater Client Full !!!\n")); NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); return ; } pReptCliEntry = &pAd->ApCfg.ApCliTab[apidx].RepeaterCli[CliIdx]; pReptCliMap = &pAd->ApCfg.ApCliTab[apidx].RepeaterCliMap[CliIdx]; /* ENTRY PREEMPTION: initialize the entry */ RTMPCancelTimer(&pReptCliEntry->ApCliAuthTimer, &Cancelled); RTMPCancelTimer(&pReptCliEntry->ApCliAssocTimer, &Cancelled); pReptCliEntry->CtrlCurrState = APCLI_CTRL_DISCONNECTED; pReptCliEntry->AuthCurrState = APCLI_AUTH_REQ_IDLE; pReptCliEntry->AssocCurrState = APCLI_ASSOC_IDLE; pReptCliEntry->CliConnectState = 0; pReptCliEntry->CliValid = FALSE; pReptCliEntry->bEthCli = FALSE; pReptCliEntry->MacTabWCID = 0xFF; pReptCliEntry->AuthReqCnt = 0; pReptCliEntry->AssocReqCnt = 0; pReptCliEntry->CliTriggerTime = 0; pReptCliEntry->pNext = NULL; pReptCliMap->pReptCliEntry = pReptCliEntry; pReptCliMap->pNext = NULL; COPY_MAC_ADDR(pReptCliEntry->OriginalAddress, pAddr); COPY_MAC_ADDR(tempMAC, pAddr); if (pAd->ApCfg.MACRepeaterOuiMode == 1) { DBGPRINT(RT_DEBUG_ERROR, (" todo !!!\n")); } else if (pAd->ApCfg.MACRepeaterOuiMode == 2) { INT IdxToUse; for (idx = 0; idx < 6; idx++) { if (RTMPEqualMemory(SPEC_ADDR[idx], pAddr, 3)) break; } /* If there is a matched one, use the next one; otherwise, use the first one. */ if (idx >= 0 && idx < 5) IdxToUse = idx + 1; else IdxToUse = 0; NdisCopyMemory(tempMAC, SPEC_ADDR[IdxToUse], 3); } else { NdisCopyMemory(tempMAC, pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, 3); } COPY_MAC_ADDR(pReptCliEntry->CurrentAddress, tempMAC); pReptCliEntry->CliEnable = TRUE; pReptCliEntry->CliConnectState = 1; pReptCliEntry->pNext = NULL; NdisGetSystemUpTime(&pReptCliEntry->CliTriggerTime); RTMPInsertRepeaterAsicEntry(pAd, CliIdx, tempMAC); HashIdx = MAC_ADDR_HASH_INDEX(tempMAC); if (pAd->ApCfg.ReptCliHash[HashIdx] == NULL) { pAd->ApCfg.ReptCliHash[HashIdx] = pReptCliEntry; } else { pCurrEntry = pAd->ApCfg.ReptCliHash[HashIdx]; #if 0 if (pCurrEntry == pReptCliEntry) { NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); return; } #endif while (pCurrEntry->pNext != NULL) pCurrEntry = pCurrEntry->pNext; pCurrEntry->pNext = pReptCliEntry; } HashIdx = MAC_ADDR_HASH_INDEX(pReptCliEntry->OriginalAddress); if (pAd->ApCfg.ReptMapHash[HashIdx] == NULL) pAd->ApCfg.ReptMapHash[HashIdx] = pReptCliMap; else { PREPEATER_CLIENT_ENTRY_MAP pCurrMapEntry; pCurrMapEntry = pAd->ApCfg.ReptMapHash[HashIdx]; while (pCurrMapEntry->pNext != NULL) pCurrMapEntry = pCurrMapEntry->pNext; pCurrMapEntry->pNext = pReptCliMap; } pAd->ApCfg.RepeaterCliSize++; NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); NdisZeroMemory(&ApCliCtrlMsg, sizeof(APCLI_CTRL_MSG_STRUCT)); ApCliCtrlMsg.Status = MLME_SUCCESS; COPY_MAC_ADDR(&ApCliCtrlMsg.SrcAddr[0], tempMAC); ApCliCtrlMsg.BssIdx = apidx; ApCliCtrlMsg.CliIdx = CliIdx; MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_MT2_AUTH_REQ, sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, apidx); } VOID RTMPRemoveRepeaterEntry( IN PRTMP_ADAPTER pAd, IN UCHAR func_tb_idx, IN UCHAR CliIdx) { USHORT HashIdx; REPEATER_CLIENT_ENTRY *pEntry, *pPrevEntry, *pProbeEntry; REPEATER_CLIENT_ENTRY_MAP *pMapEntry, *pPrevMapEntry, *pProbeMapEntry; BOOLEAN bVaild; DBGPRINT(RT_DEBUG_ERROR, (" %s.\n", __FUNCTION__)); RTMPRemoveRepeaterAsicEntry(pAd, CliIdx); NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); pEntry = &pAd->ApCfg.ApCliTab[func_tb_idx].RepeaterCli[CliIdx]; bVaild = TRUE; HashIdx = MAC_ADDR_HASH_INDEX(pEntry->CurrentAddress); pPrevEntry = NULL; pProbeEntry = pAd->ApCfg.ReptCliHash[HashIdx]; ASSERT(pProbeEntry); if (pProbeEntry == NULL) { bVaild = FALSE; goto done; } if (pProbeEntry != NULL) { /* update Hash list*/ do { if (pProbeEntry == pEntry) { if (pPrevEntry == NULL) { pAd->ApCfg.ReptCliHash[HashIdx] = pEntry->pNext; } else { pPrevEntry->pNext = pEntry->pNext; } break; } pPrevEntry = pProbeEntry; pProbeEntry = pProbeEntry->pNext; } while (pProbeEntry); } /* not found !!!*/ ASSERT(pProbeEntry != NULL); if (pProbeEntry == NULL) { bVaild = FALSE; goto done; } pMapEntry = &pAd->ApCfg.ApCliTab[func_tb_idx].RepeaterCliMap[CliIdx]; HashIdx = MAC_ADDR_HASH_INDEX(pEntry->OriginalAddress); pPrevMapEntry = NULL; pProbeMapEntry = pAd->ApCfg.ReptMapHash[HashIdx]; ASSERT(pProbeMapEntry); if (pProbeMapEntry != NULL) { /* update Hash list*/ do { if (pProbeMapEntry == pMapEntry) { if (pPrevMapEntry == NULL) { pAd->ApCfg.ReptMapHash[HashIdx] = pMapEntry->pNext; } else { pPrevMapEntry->pNext = pMapEntry->pNext; } break; } pPrevMapEntry = pProbeMapEntry; pProbeMapEntry = pProbeMapEntry->pNext; } while (pProbeMapEntry); } /* not found !!!*/ ASSERT(pProbeMapEntry != NULL); done: pAd->ApCfg.ApCliTab[func_tb_idx].RepeaterCli[CliIdx].CliConnectState = 0; NdisZeroMemory(pAd->ApCfg.ApCliTab[func_tb_idx].RepeaterCli[CliIdx].OriginalAddress, MAC_ADDR_LEN); if (bVaild == TRUE) pAd->ApCfg.RepeaterCliSize--; NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); return; } MAC_TABLE_ENTRY *RTMPInsertRepeaterMacEntry( IN RTMP_ADAPTER *pAd, IN UCHAR *pAddr, IN struct wifi_dev *wdev, IN UCHAR apIdx, IN UCHAR cliIdx, IN BOOLEAN CleanAll) { UCHAR HashIdx; int i; MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; BOOLEAN Cancelled; if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) return NULL; /* allocate one MAC entry*/ NdisAcquireSpinLock(&pAd->MacTabLock); i = (MAX_NUMBER_OF_MAC + ((MAX_EXT_MAC_ADDR_SIZE + 1) * (apIdx - MIN_NET_DEVICE_FOR_APCLI))); if (cliIdx != 0xFF) i = i + cliIdx + 1; /* pick up the first available vacancy*/ if (IS_ENTRY_NONE(&pAd->MacTab.Content[i])) { pEntry = &pAd->MacTab.Content[i]; /* ENTRY PREEMPTION: initialize the entry */ if (pEntry->RetryTimer.Valid) RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); if (pEntry->EnqueueStartForPSKTimer.Valid) RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled); #ifdef DOT11W_PMF_SUPPORT RTMPCancelTimer(&pEntry->SAQueryTimer, &Cancelled); RTMPCancelTimer(&pEntry->SAQueryConfirmTimer, &Cancelled); #endif /* DOT11W_PMF_SUPPORT */ NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); if (CleanAll == TRUE) { pEntry->MaxSupportedRate = RATE_11; pEntry->CurrTxRate = RATE_11; NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY)); pEntry->PairwiseKey.KeyLen = 0; pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; } #ifdef CONFIG_AP_SUPPORT #ifdef APCLI_SUPPORT if (apIdx >= MIN_NET_DEVICE_FOR_APCLI) { SET_ENTRY_APCLI(pEntry); } #endif /* APCLI_SUPPORT */ #endif /* CONFIG_AP_SUPPORT */ pEntry->wdev = wdev; pEntry->wcid = i; //SET_ENTRY_AP(pEntry);//Carter, why set Apcli Entry then set to AP entry? pAd->MacTab.tr_entry[i].isCached = FALSE; //tr_entry->isCached = FALSE; pEntry->bIAmBadAtheros = FALSE; RTMPInitTimer(pAd, &pEntry->EnqueueStartForPSKTimer, GET_TIMER_FUNCTION(EnqueueStartForPSKExec), pEntry, FALSE); #ifdef APCLI_SUPPORT if (IS_ENTRY_APCLI(pEntry)) { RTMPInitTimer(pAd, &pEntry->RetryTimer, GET_TIMER_FUNCTION(WPARetryExec), pEntry, FALSE); } #endif /* APCLI_SUPPORT */ #ifdef TXBF_SUPPORT if (pAd->chipCap.FlgHwTxBfCap) RTMPInitTimer(pAd, &pEntry->eTxBfProbeTimer, GET_TIMER_FUNCTION(eTxBfProbeTimerExec), pEntry, FALSE); #endif /* TXBF_SUPPORT */ pEntry->pAd = pAd; pEntry->CMTimerRunning = FALSE; pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; pEntry->RSNIE_Len = 0; NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter)); pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; pEntry->func_tb_idx = (apIdx - MIN_NET_DEVICE_FOR_APCLI); if (IS_ENTRY_APCLI(pEntry)) pEntry->apidx = (apIdx - MIN_NET_DEVICE_FOR_APCLI); pEntry->pMbss = NULL; #ifdef APCLI_SUPPORT if (IS_ENTRY_APCLI(pEntry)) { pEntry->AuthMode = pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].wdev.AuthMode; pEntry->WepStatus = pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].wdev.WepStatus; if (pEntry->AuthMode < Ndis802_11AuthModeWPA) { pEntry->WpaState = AS_NOTUSE; pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; } else { pEntry->WpaState = AS_PTKSTART; pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; } } #endif /* APCLI_SUPPORT */ pEntry->GTKState = REKEY_NEGOTIATING; pEntry->PairwiseKey.KeyLen = 0; pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; pAd->MacTab.tr_entry[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; //pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; COPY_MAC_ADDR(pEntry->Addr, pAddr); #ifdef APCLI_SUPPORT if (IS_ENTRY_APCLI(pEntry)) { COPY_MAC_ADDR(pEntry->bssid, pAddr); } #endif // APCLI_SUPPORT // pEntry->Sst = SST_NOT_AUTH; pEntry->AuthState = AS_NOT_AUTH; pEntry->Aid = (USHORT)i; pEntry->CapabilityInfo = 0; pEntry->PsMode = PWR_ACTIVE; pAd->MacTab.tr_entry[i].PsQIdleCount = 0; pAd->MacTab.tr_entry[i].PsTokenFlag = 0; //pEntry->PsQIdleCount = 0; pEntry->NoDataIdleCount = 0; pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT; pEntry->ContinueTxFailCnt = 0; pEntry->TimeStamp_toTxRing = 0; // TODO: shiang-usw, remove upper setting becasue we need to migrate to tr_entry! pAd->MacTab.tr_entry[i].PsMode = PWR_ACTIVE; pAd->MacTab.tr_entry[i].NoDataIdleCount = 0; pAd->MacTab.tr_entry[i].ContinueTxFailCnt = 0; pAd->MacTab.tr_entry[i].LockEntryTx = FALSE; pAd->MacTab.tr_entry[i].TimeStamp_toTxRing = 0; pAd->MacTab.Size ++; /* Set the security mode of this entry as OPEN-NONE in ASIC */ RTMP_REMOVE_PAIRWISE_KEY_ENTRY(pAd, (UCHAR)i); /* Add this entry into ASIC RX WCID search table */ RTMP_STA_ENTRY_ADD(pAd, pEntry); #ifdef TXBF_SUPPORT if (pAd->chipCap.FlgHwTxBfCap) NdisAllocateSpinLock(pAd, &pEntry->TxSndgLock); #endif /* TXBF_SUPPORT */ DBGPRINT(RT_DEBUG_TRACE, ("%s - allocate entry #%d, Aid = %d, Total= %d\n",__FUNCTION__, i, pEntry->Aid, pAd->MacTab.Size)); } else { DBGPRINT(RT_DEBUG_ERROR, ("%s - exist entry #%d, Aid = %d, Total= %d\n", __FUNCTION__, i, pEntry->Aid, pAd->MacTab.Size)); NdisReleaseSpinLock(&pAd->MacTabLock); return pEntry; } /* add this MAC entry into HASH table */ if (pEntry) { HashIdx = MAC_ADDR_HASH_INDEX(pAddr); if (pAd->MacTab.Hash[HashIdx] == NULL) { pAd->MacTab.Hash[HashIdx] = pEntry; } else { pCurrEntry = pAd->MacTab.Hash[HashIdx]; while (pCurrEntry->pNext != NULL) pCurrEntry = pCurrEntry->pNext; pCurrEntry->pNext = pEntry; } #ifdef SMART_ANTENNA pEntry->mcsInUse = -1; #endif /* SMART_ANTENNA */ } NdisReleaseSpinLock(&pAd->MacTabLock); /*update tx burst, must after unlock pAd->MacTabLock*/ rtmp_tx_burst_set(pAd); return pEntry; } VOID RTMPRepeaterReconnectionCheck( IN PRTMP_ADAPTER pAd) { #ifdef APCLI_AUTO_CONNECT_SUPPORT INT i; PCHAR pApCliSsid, pApCliCfgSsid; UCHAR CfgSsidLen; NDIS_802_11_SSID Ssid; if (pAd->ApCfg.bMACRepeaterEn && pAd->ApCfg.MACRepeaterOuiMode == 2 && pAd->ApCfg.ApCliAutoConnectRunning == FALSE) { for (i = 0; i < MAX_APCLI_NUM; i++) { pApCliSsid = pAd->ApCfg.ApCliTab[i].Ssid; pApCliCfgSsid = pAd->ApCfg.ApCliTab[i].CfgSsid; CfgSsidLen = pAd->ApCfg.ApCliTab[i].CfgSsidLen; if ((pAd->ApCfg.ApCliTab[i].CtrlCurrState < APCLI_CTRL_AUTH || !NdisEqualMemory(pApCliSsid, pApCliCfgSsid, CfgSsidLen)) && pAd->ApCfg.ApCliTab[i].CfgSsidLen > 0 && pAd->Mlme.OneSecPeriodicRound % 23 == 0) { DBGPRINT(RT_DEBUG_TRACE, (" %s(): Scan channels for AP (%s)\n", __FUNCTION__, pApCliCfgSsid)); pAd->ApCfg.ApCliAutoConnectRunning = TRUE; Ssid.SsidLength = CfgSsidLen; NdisCopyMemory(Ssid.Ssid, pApCliCfgSsid, CfgSsidLen); ApSiteSurvey(pAd, &Ssid, SCAN_ACTIVE, FALSE); } } } #endif /* APCLI_AUTO_CONNECT_SUPPORT */ } BOOLEAN RTMPRepeaterVaildMacEntry( IN PRTMP_ADAPTER pAd, IN PUCHAR pAddr) { INVAILD_TRIGGER_MAC_ENTRY *pEntry = NULL; if (pAd->ApCfg.RepeaterCliSize >= MAX_EXT_MAC_ADDR_SIZE) return FALSE; if(IS_MULTICAST_MAC_ADDR(pAddr)) return FALSE; if(IS_BROADCAST_MAC_ADDR(pAddr)) return FALSE; pEntry = RepeaterInvaildMacLookup(pAd, pAddr); if (pEntry) return FALSE; else return TRUE; } INVAILD_TRIGGER_MAC_ENTRY *RepeaterInvaildMacLookup( IN PRTMP_ADAPTER pAd, IN PUCHAR pAddr) { ULONG HashIdx; INVAILD_TRIGGER_MAC_ENTRY *pEntry = NULL; HashIdx = MAC_ADDR_HASH_INDEX(pAddr); pEntry = pAd->ApCfg.ReptControl.ReptInvaildHash[HashIdx]; while (pEntry) { if (MAC_ADDR_EQUAL(pEntry->MacAddr, pAddr)) { break; } else pEntry = pEntry->pNext; } if (pEntry && pEntry->bInsert) return pEntry; else return NULL; } VOID RTMPRepeaterInsertInvaildMacEntry( IN PRTMP_ADAPTER pAd, IN PUCHAR pAddr) { UCHAR HashIdx, idx = 0; INVAILD_TRIGGER_MAC_ENTRY *pEntry = NULL; INVAILD_TRIGGER_MAC_ENTRY *pCurrEntry = NULL; if (pAd->ApCfg.ReptControl.ReptInVaildMacSize >= 32) return; if (MAC_ADDR_EQUAL(pAddr, ZERO_MAC_ADDR)) return; NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); for (idx = 0; idx< 32; idx++) { pEntry = &pAd->ApCfg.ReptControl.RepeaterInvaildEntry[idx]; if (MAC_ADDR_EQUAL(pEntry->MacAddr, pAddr)) { if (pEntry->bInsert) { NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); return; } } /* pick up the first available vacancy*/ if (pEntry->bInsert == FALSE) { NdisZeroMemory(pEntry->MacAddr, MAC_ADDR_LEN); COPY_MAC_ADDR(pEntry->MacAddr, pAddr); pEntry->bInsert = TRUE; break; } } /* add this entry into HASH table */ if (pEntry) { HashIdx = MAC_ADDR_HASH_INDEX(pAddr); pEntry->pNext = NULL; if (pAd->ApCfg.ReptControl.ReptInvaildHash[HashIdx] == NULL) { pAd->ApCfg.ReptControl.ReptInvaildHash[HashIdx] = pEntry; } else { pCurrEntry = pAd->ApCfg.ReptControl.ReptInvaildHash[HashIdx]; while (pCurrEntry->pNext != NULL) pCurrEntry = pCurrEntry->pNext; pCurrEntry->pNext = pEntry; } } DBGPRINT(RT_DEBUG_ERROR, (" Store Invaild MacAddr = %02x:%02x:%02x:%02x:%02x:%02x. !!!\n", PRINT_MAC(pEntry->MacAddr))); pAd->ApCfg.ReptControl.ReptInVaildMacSize++; NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); return; } BOOLEAN RTMPRepeaterRemoveInvaildMacEntry( IN PRTMP_ADAPTER pAd, IN UCHAR idx, IN PUCHAR pAddr) { USHORT HashIdx; INVAILD_TRIGGER_MAC_ENTRY *pEntry = NULL; INVAILD_TRIGGER_MAC_ENTRY *pPrevEntry, *pProbeEntry; NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); HashIdx = MAC_ADDR_HASH_INDEX(pAddr); pEntry = &pAd->ApCfg.ReptControl.RepeaterInvaildEntry[idx]; if (pEntry && pEntry->bInsert) { pPrevEntry = NULL; pProbeEntry = pAd->ApCfg.ReptControl.ReptInvaildHash[HashIdx]; ASSERT(pProbeEntry); if (pProbeEntry != NULL) { /* update Hash list*/ do { if (pProbeEntry == pEntry) { if (pPrevEntry == NULL) { pAd->ApCfg.ReptControl.ReptInvaildHash[HashIdx] = pEntry->pNext; } else { pPrevEntry->pNext = pEntry->pNext; } break; } pPrevEntry = pProbeEntry; pProbeEntry = pProbeEntry->pNext; } while (pProbeEntry); } /* not found !!!*/ ASSERT(pProbeEntry != NULL); pAd->ApCfg.ReptControl.ReptInVaildMacSize--; } NdisZeroMemory(pEntry->MacAddr, MAC_ADDR_LEN); pEntry->bInsert = FALSE; NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); return TRUE; } INT Show_Repeater_Cli_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) { INT i; //UINT32 RegValue; ULONG DataRate=0; if (!pAd->ApCfg.bMACRepeaterEn) return TRUE; DBGPRINT(RT_DEBUG_OFF, ("\n")); #ifdef DOT11_N_SUPPORT DBGPRINT(RT_DEBUG_OFF, ("HT Operating Mode : %d\n", pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode)); DBGPRINT(RT_DEBUG_OFF, ("\n")); #endif /* DOT11_N_SUPPORT */ DBGPRINT(RT_DEBUG_OFF, ("\n%-19s%-4s%-4s%-4s%-4s%-8s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s%-7s%-7s\n", "MAC", "AID", "BSS", "PSM", "WMM", "MIMOPS", "RSSI0", "RSSI1", "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC", "Idle", "Rate")); for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) { PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i]; if (pEntry && IS_ENTRY_APCLI(pEntry)&& (pEntry->Sst == SST_ASSOC) && (pEntry->bReptCli)) { DataRate=0; getRate(pEntry->HTPhyMode, &DataRate); DBGPRINT(RT_DEBUG_OFF, ("%02X:%02X:%02X:%02X:%02X:%02X ", pEntry->ReptCliAddr[0], pEntry->ReptCliAddr[1], pEntry->ReptCliAddr[2], pEntry->ReptCliAddr[3], pEntry->ReptCliAddr[4], pEntry->ReptCliAddr[5])); DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->Aid)); DBGPRINT(RT_DEBUG_OFF, ("%-4d-%d", (int)pEntry->apidx, pEntry->func_tb_idx)); DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->PsMode)); DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))); #ifdef DOT11_N_SUPPORT DBGPRINT(RT_DEBUG_OFF, ("%-8d", (int)pEntry->MmpsMode)); #endif /* DOT11_N_SUPPORT */) DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi[0])); DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi[1])); DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi[2])); DBGPRINT(RT_DEBUG_OFF, ("%-10s", get_phymode_str(pEntry->HTPhyMode.field.MODE))); DBGPRINT(RT_DEBUG_OFF, ("%-6s", get_bw_str(pEntry->HTPhyMode.field.BW))); DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.MCS)); DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.ShortGI)); DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.STBC)); DBGPRINT(RT_DEBUG_OFF, ("%-7d", (int)(pEntry->StaIdleTimeout - pEntry->NoDataIdleCount))); DBGPRINT(RT_DEBUG_OFF, ("%-7d", (int)DataRate)); DBGPRINT(RT_DEBUG_OFF, ("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount, (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0)); DBGPRINT(RT_DEBUG_OFF, ("\n")); } } return TRUE; } #endif /* MAC_REPEATER_SUPPORT */