VOID CMDHandler( IN PRTMP_ADAPTER pAd) { PCmdQElmt cmdqelmt; PUCHAR pData; NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; // ULONG Now = 0; NTSTATUS ntStatus; // unsigned long IrqFlags; while (pAd && pAd->CmdQ.size > 0) { NdisStatus = NDIS_STATUS_SUCCESS; NdisAcquireSpinLock(&pAd->CmdQLock); RTThreadDequeueCmd(&pAd->CmdQ, &cmdqelmt); NdisReleaseSpinLock(&pAd->CmdQLock); if (cmdqelmt == NULL) break; pData = cmdqelmt->buffer; if(!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { switch (cmdqelmt->command) { case CMDTHREAD_CHECK_GPIO: { #ifdef CONFIG_STA_SUPPORT UINT32 data; #endif // CONFIG_STA_SUPPORT // #ifdef RALINK_ATE if(ATE_ON(pAd)) { ATEDBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); break; } #endif // RALINK_ATE // #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { // Read GPIO pin2 as Hardware controlled radio state RTUSBReadMACRegister( pAd, GPIO_CTRL_CFG, &data); if (data & 0x04) { pAd->StaCfg.bHwRadio = TRUE; } else { pAd->StaCfg.bHwRadio = FALSE; } if(pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) { pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); if(pAd->StaCfg.bRadio == TRUE) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("!!! Radio On !!!\n")); MlmeRadioOn(pAd); // Update extra information pAd->ExtraInfo = EXTRA_INFO_CLEAR; } else { DBGPRINT_RAW(RT_DEBUG_ERROR, ("!!! Radio Off !!!\n")); MlmeRadioOff(pAd); // Update extra information pAd->ExtraInfo = HW_RADIO_OFF; } } } #endif // CONFIG_STA_SUPPORT // } break; #ifdef CONFIG_STA_SUPPORT case CMDTHREAD_QKERIODIC_EXECUT: { StaQuickResponeForRateUpExec(NULL, pAd, NULL, NULL); } break; #endif // CONFIG_STA_SUPPORT // case CMDTHREAD_RESET_BULK_OUT: { UINT32 MACValue; UCHAR Index; int ret=0; PHT_TX_CONTEXT pHTTXContext; // RTMP_TX_RING *pTxRing; unsigned long IrqFlags; DBGPRINT(RT_DEBUG_TRACE, ("CMDTHREAD_RESET_BULK_OUT(ResetPipeid=0x%0x)===>\n", pAd->bulkResetPipeid)); // All transfers must be aborted or cancelled before attempting to reset the pipe. //RTUSBCancelPendingBulkOutIRP(pAd); // Wait 10ms to let previous packet that are already in HW FIFO to clear. by MAXLEE 12-25-2007 Index = 0; do { if(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) break; RTUSBReadMACRegister(pAd, TXRXQ_PCNT, &MACValue); if ((MACValue & 0xf00000/*0x800000*/) == 0) break; Index++; RTMPusecDelay(10000); }while(Index < 100); MACValue = 0; RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); // 2nd, to prevent Read Register error, we check the validity. if ((MACValue & 0xc00000) == 0) RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); // 3rd, to prevent Read Register error, we check the validity. if ((MACValue & 0xc00000) == 0) RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); MACValue |= 0x80000; RTUSBWriteMACRegister(pAd, USB_DMA_CFG, MACValue); // Wait 1ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007 RTMPusecDelay(1000); MACValue &= (~0x80000); RTUSBWriteMACRegister(pAd, USB_DMA_CFG, MACValue); DBGPRINT(RT_DEBUG_TRACE, ("\tSet 0x2a0 bit19. Clear USB DMA TX path\n")); // Wait 5ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007 //RTMPusecDelay(5000); if ((pAd->bulkResetPipeid & BULKOUT_MGMT_RESET_FLAG) == BULKOUT_MGMT_RESET_FLAG) { RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); if (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE /* pMLMEContext->bWaitingBulkOut == TRUE */) { RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); } RTUSBKickBulkOut(pAd); DBGPRINT(RT_DEBUG_TRACE, ("\tTX MGMT RECOVER Done!\n")); } else { pHTTXContext = &(pAd->TxContext[pAd->bulkResetPipeid]); //NdisAcquireSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); if ( pAd->BulkOutPending[pAd->bulkResetPipeid] == FALSE) { pAd->BulkOutPending[pAd->bulkResetPipeid] = TRUE; pHTTXContext->IRPPending = TRUE; pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 1; // no matter what, clean the flag RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); //NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); #ifdef RALINK_ATE if(ATE_ON(pAd)) { ret = ATEResetBulkOut(pAd); } else #endif // RALINK_ATE // { RTUSBInitHTTxDesc(pAd, pHTTXContext, pAd->bulkResetPipeid, pHTTXContext->BulkOutSize, (usb_complete_t)RTUSBBulkOutDataPacketComplete); if((ret = RTUSB_SUBMIT_URB(pHTTXContext->pUrb))!=0) { RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); pAd->BulkOutPending[pAd->bulkResetPipeid] = FALSE; pHTTXContext->IRPPending = FALSE; pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 0; RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); DBGPRINT(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_OUT:Submit Tx URB failed %d\n", ret)); } else { RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); DBGPRINT(RT_DEBUG_TRACE,("\tCMDTHREAD_RESET_BULK_OUT: TxContext[%d]:CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, pending=%d!\n", pAd->bulkResetPipeid, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad, pAd->BulkOutPending[pAd->bulkResetPipeid])); DBGPRINT(RT_DEBUG_TRACE,("\t\tBulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther)); RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); DBGPRINT(RT_DEBUG_TRACE, ("\tCMDTHREAD_RESET_BULK_OUT: Submit Tx DATA URB for failed BulkReq(0x%lx) Done, status=%d!\n", pAd->bulkResetReq[pAd->bulkResetPipeid], pHTTXContext->pUrb->rtusb_urb_status)); } } } else { //NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); //RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); DBGPRINT(RT_DEBUG_ERROR, ("CmdThread : TX DATA RECOVER FAIL for BulkReq(0x%lx) because BulkOutPending[%d] is TRUE!\n", pAd->bulkResetReq[pAd->bulkResetPipeid], pAd->bulkResetPipeid)); if (pAd->bulkResetPipeid == 0) { UCHAR pendingContext = 0; PHT_TX_CONTEXT pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[pAd->bulkResetPipeid ]); PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa); PTX_CONTEXT pNULLContext = (PTX_CONTEXT)(&pAd->PsPollContext); PTX_CONTEXT pPsPollContext = (PTX_CONTEXT)(&pAd->NullContext); if (pHTTXContext->IRPPending) pendingContext |= 1; else if (pMLMEContext->IRPPending) pendingContext |= 2; else if (pNULLContext->IRPPending) pendingContext |= 4; else if (pPsPollContext->IRPPending) pendingContext |= 8; else pendingContext = 0; DBGPRINT(RT_DEBUG_ERROR, ("\tTX Occupied by %d!\n", pendingContext)); } // no matter what, clean the flag RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << pAd->bulkResetPipeid)); } RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); //RTUSBKickBulkOut(pAd); } } /* // Don't cancel BULKIN. while ((atomic_read(&pAd->PendingRx) > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { if (atomic_read(&pAd->PendingRx) > 0) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkIn IRP Pending!!cancel it!\n")); RTUSBCancelPendingBulkInIRP(pAd); } RTMPusecDelay(100000); } if ((atomic_read(&pAd->PendingRx) == 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { UCHAR i; RTUSBRxPacket(pAd); pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index pAd->NextRxBulkInIndex = 0; // Rx Bulk pointer for (i = 0; i < (RX_RING_SIZE); i++) { PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); pRxContext->pAd = pAd; pRxContext->InUse = FALSE; pRxContext->IRPPending = FALSE; pRxContext->Readable = FALSE; pRxContext->ReorderInUse = FALSE; } RTUSBBulkReceive(pAd); DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTUSBBulkReceive\n")); }*/ DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_OUT<===\n")); break; case CMDTHREAD_RESET_BULK_IN: DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN === >\n")); // All transfers must be aborted or cancelled before attempting to reset the pipe. { UINT32 MACValue; #ifdef RALINK_ATE if (ATE_ON(pAd)) { ATEResetBulkIn(pAd); } else #endif // RALINK_ATE // { //while ((atomic_read(&pAd->PendingRx) > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) if((pAd->PendingRx > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkIn IRP Pending!!!\n")); RTUSBCancelPendingBulkInIRP(pAd); RTMPusecDelay(100000); pAd->PendingRx = 0; } } // Wait 10ms before reading register. RTMPusecDelay(10000); ntStatus = RTUSBReadMACRegister(pAd, MAC_CSR0, &MACValue); if ((NT_SUCCESS(ntStatus) == TRUE) && (!(RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))))) { UCHAR i; if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))) break; pAd->NextRxBulkInPosition = pAd->RxContext[pAd->NextRxBulkInIndex].BulkInOffset; DBGPRINT(RT_DEBUG_TRACE, ("BULK_IN_RESET: NBIIdx=0x%x,NBIRIdx=0x%x, BIRPos=0x%lx. BIReq=x%lx, BIComplete=0x%lx, BICFail0x%lx\n", pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex, pAd->NextRxBulkInPosition, pAd->BulkInReq, pAd->BulkInComplete, pAd->BulkInCompleteFail)); for (i = 0; i < RX_RING_SIZE; i++) { DBGPRINT(RT_DEBUG_TRACE, ("\tRxContext[%d]: IRPPending=%d, InUse=%d, Readable=%d!\n" , i, pAd->RxContext[i].IRPPending, pAd->RxContext[i].InUse, pAd->RxContext[i].Readable)); } /* DBGPRINT_RAW(RT_DEBUG_ERROR, ("==========================================\n")); pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index pAd->NextRxBulkInIndex = 0; // Rx Bulk pointer for (i = 0; i < (RX_RING_SIZE); i++) { PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); pRxContext->pAd = pAd; pRxContext->InUse = FALSE; pRxContext->IRPPending = FALSE; pRxContext->Readable = FALSE; pRxContext->ReorderInUse = FALSE; }*/ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); for (i = 0; i < pAd->CommonCfg.NumOfBulkInIRP; i++) { //RTUSBBulkReceive(pAd); PRX_CONTEXT pRxContext; PURB pUrb; int ret = 0; unsigned long IrqFlags; RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]); if ((pAd->PendingRx > 0) || (pRxContext->Readable == TRUE) || (pRxContext->InUse == TRUE)) { RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); break; } pRxContext->InUse = TRUE; pRxContext->IRPPending = TRUE; pAd->PendingRx++; pAd->BulkInReq++; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); // Init Rx context descriptor RTUSBInitRxDesc(pAd, pRxContext); pUrb = pRxContext->pUrb; if ((ret = RTUSB_SUBMIT_URB(pUrb))!=0) { // fail RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext->InUse = FALSE; pRxContext->IRPPending = FALSE; pAd->PendingRx--; pAd->BulkInReq--; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); DBGPRINT(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB failed(%d), status=%d\n", ret, pUrb->rtusb_urb_status)); } else { // success //DBGPRINT(RT_DEBUG_TRACE, ("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", // pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex)); DBGPRINT_RAW(RT_DEBUG_TRACE, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB Done, status=%d!\n", pUrb->rtusb_urb_status)); ASSERT((pRxContext->InUse == pRxContext->IRPPending)); } } } else { // Card must be removed if (NT_SUCCESS(ntStatus) != TRUE) { RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); DBGPRINT_RAW(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Read Register Failed!Card must be removed!!\n\n")); } else { DBGPRINT_RAW(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Cannot do bulk in because flags(0x%lx) on !\n", pAd->Flags)); } } } DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN <===\n")); break; case CMDTHREAD_SET_ASIC_WCID: { RT_SET_ASIC_WCID SetAsicWcid; USHORT offset; UINT32 MACValue, MACRValue = 0; SetAsicWcid = *((PRT_SET_ASIC_WCID)(pData)); if (SetAsicWcid.WCID >= MAX_LEN_OF_MAC_TABLE) return; offset = MAC_WCID_BASE + ((UCHAR)SetAsicWcid.WCID)*HW_WCID_ENTRY_SIZE; DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_SET_ASIC_WCID : WCID = %ld, SetTid = %lx, DeleteTid = %lx.\n", SetAsicWcid.WCID, SetAsicWcid.SetTid, SetAsicWcid.DeleteTid)); MACValue = (pAd->MacTab.Content[SetAsicWcid.WCID].Addr[3]<<24)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[2]<<16)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[1]<<8)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[0]); DBGPRINT_RAW(RT_DEBUG_TRACE, ("1-MACValue= %x,\n", MACValue)); RTUSBWriteMACRegister(pAd, offset, MACValue); // Read bitmask RTUSBReadMACRegister(pAd, offset+4, &MACRValue); if ( SetAsicWcid.DeleteTid != 0xffffffff) MACRValue &= (~SetAsicWcid.DeleteTid); if (SetAsicWcid.SetTid != 0xffffffff) MACRValue |= (SetAsicWcid.SetTid); MACRValue &= 0xffff0000; MACValue = (pAd->MacTab.Content[SetAsicWcid.WCID].Addr[5]<<8)+pAd->MacTab.Content[SetAsicWcid.WCID].Addr[4]; MACValue |= MACRValue; RTUSBWriteMACRegister(pAd, offset+4, MACValue); DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-MACValue= %x,\n", MACValue)); } break; /* Security Related for Asic command */ case CMDTHREAD_SET_WCID_SEC_INFO: { PRT_ASIC_WCID_SEC_INFO pInfo; pInfo = (PRT_ASIC_WCID_SEC_INFO)pData; RTMPSetWcidSecurityInfo(pAd, pInfo->BssIdx, pInfo->KeyIdx, pInfo->CipherAlg, pInfo->Wcid, pInfo->KeyTabFlag); } break; case CMDTHREAD_SET_ASIC_WCID_IVEIV: { PRT_ASIC_WCID_IVEIV_ENTRY pInfo; pInfo = (PRT_ASIC_WCID_IVEIV_ENTRY)pData; AsicUpdateWCIDIVEIV(pAd, pInfo->Wcid, pInfo->Iv, pInfo->Eiv); } break; case CMDTHREAD_SET_ASIC_WCID_ATTR: { PRT_ASIC_WCID_ATTR_ENTRY pInfo; pInfo = (PRT_ASIC_WCID_ATTR_ENTRY)pData; AsicUpdateWcidAttributeEntry(pAd, pInfo->BssIdx, pInfo->KeyIdx, pInfo->CipherAlg, pInfo->Wcid, pInfo->KeyTabFlag); } break; case CMDTHREAD_SET_ASIC_SHARED_KEY: { PRT_ASIC_SHARED_KEY pInfo; pInfo = (PRT_ASIC_SHARED_KEY)pData; AsicAddSharedKeyEntry(pAd, pInfo->BssIndex, pInfo->KeyIdx, &pInfo->CipherKey); } break; case CMDTHREAD_SET_ASIC_PAIRWISE_KEY: { PRT_ASIC_PAIRWISE_KEY pInfo; pInfo = (PRT_ASIC_PAIRWISE_KEY)pData; AsicAddPairwiseKeyEntry(pAd, pInfo->WCID, &pInfo->CipherKey); } break; case CMDTHREAD_SET_PORT_SECURED: { #ifdef CONFIG_STA_SUPPORT STA_PORT_SECURED(pAd); #endif // CONFIG_STA_SUPPORT // } break; case CMDTHREAD_REMOVE_PAIRWISE_KEY: { UCHAR Wcid = *((PUCHAR)(pData)); AsicRemovePairwiseKeyEntry(pAd, Wcid); } break; case CMDTHREAD_SET_CLIENT_MAC_ENTRY: { PRT_SET_ASIC_WCID pInfo; pInfo = (PRT_SET_ASIC_WCID)pData; AsicUpdateRxWCIDTable(pAd, pInfo->WCID, pInfo->Addr); } break; // add by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet case CMDTHREAD_UPDATE_PROTECT: { AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT), TRUE, 0); } break; // end johnli case CMDTHREAD_802_11_COUNTER_MEASURE: break; #ifdef CONFIG_STA_SUPPORT case CMDTHREAD_SET_PSM_BIT: IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { USHORT *pPsm = (USHORT *)pData; MlmeSetPsmBit(pAd, *pPsm); } break; case CMDTHREAD_FORCE_WAKE_UP: IF_DEV_CONFIG_OPMODE_ON_STA(pAd) AsicForceWakeup(pAd, TRUE); break; case CMDTHREAD_FORCE_SLEEP_AUTO_WAKEUP: { USHORT TbttNumToNextWakeUp; USHORT NextDtim = pAd->StaCfg.DtimPeriod; ULONG Now; NdisGetSystemUpTime(&Now); NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod; TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) TbttNumToNextWakeUp = NextDtim; RTMP_SET_PSM_BIT(pAd, PWR_SAVE); // if WMM-APSD is failed, try to disable following line AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); } break; #endif // CONFIG_STA_SUPPORT // default: DBGPRINT(RT_DEBUG_ERROR, ("--> Control Thread !! ERROR !! Unknown(cmdqelmt->command=0x%x) !! \n", cmdqelmt->command)); break; } } if (cmdqelmt->CmdFromNdis == TRUE) { if (cmdqelmt->buffer != NULL) os_free_mem(pAd, cmdqelmt->buffer); os_free_mem(pAd, cmdqelmt); } else { if ((cmdqelmt->buffer != NULL) && (cmdqelmt->bufferlength != 0)) os_free_mem(pAd, cmdqelmt->buffer); os_free_mem(pAd, cmdqelmt); } } /* end of while */ }
VOID PeerBeacon( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN]; CHAR Ssid[MAX_LEN_OF_SSID]; CF_PARM CfParm; UCHAR SsidLen, MessageToMe=0, BssType, Channel, NewChannel, index=0; UCHAR DtimCount=0, DtimPeriod=0, BcastFlag=0; USHORT CapabilityInfo, AtimWin, BeaconPeriod; LARGE_INTEGER TimeStamp; USHORT TbttNumToNextWakeUp; UCHAR Erp; UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; UCHAR SupRateLen, ExtRateLen; UCHAR CkipFlag; USHORT LenVIE; UCHAR AironetCellPowerLimit; EDCA_PARM EdcaParm; QBSS_LOAD_PARM QbssLoad; QOS_CAPABILITY_PARM QosCapability; ULONG RalinkIe; UCHAR VarIE[MAX_VIE_LEN]; NDIS_802_11_VARIABLE_IEs *pVIE = NULL; HT_CAPABILITY_IE HtCapability; ADD_HT_INFO_IE AddHtInfo; UCHAR HtCapabilityLen, PreNHtCapabilityLen; UCHAR AddHtInfoLen; UCHAR NewExtChannelOffset = 0xff; #ifdef RALINK_ATE if (ATE_ON(pAd)) { return; } #endif if (!(INFRA_ON(pAd) || ADHOC_ON(pAd) )) return; pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; pVIE->Length = 0; RTMPZeroMemory(&HtCapability, sizeof(HtCapability)); RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE)); if (PeerBeaconAndProbeRspSanity(pAd, Elem->Msg, Elem->MsgLen, Elem->Channel, Addr2, Bssid, Ssid, &SsidLen, &BssType, &BeaconPeriod, &Channel, &NewChannel, &TimeStamp, &CfParm, &AtimWin, &CapabilityInfo, &Erp, &DtimCount, &DtimPeriod, &BcastFlag, &MessageToMe, SupRate, &SupRateLen, ExtRate, &ExtRateLen, &CkipFlag, &AironetCellPowerLimit, &EdcaParm, &QbssLoad, &QosCapability, &RalinkIe, &HtCapabilityLen, &PreNHtCapabilityLen, &HtCapability, &AddHtInfoLen, &AddHtInfo, &NewExtChannelOffset, &LenVIE, pVIE)) { BOOLEAN is_my_bssid, is_my_ssid; ULONG Bssidx, Now; BSS_ENTRY *pBss; CHAR RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2)); is_my_bssid = MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid)? TRUE : FALSE; is_my_ssid = SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)? TRUE:FALSE; if ((! is_my_ssid) && (! is_my_bssid)) return; if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC) return; #ifdef DOT11_N_SUPPORT if (AddHtInfoLen != 0) Channel = AddHtInfo.ControlChan; if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) HtCapabilityLen = SIZE_HT_CAP_IE; #endif Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); if (Bssidx == BSS_NOT_FOUND) { Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, &AddHtInfo,HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel, RealRssi, TimeStamp, CkipFlag, &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); if (Bssidx == BSS_NOT_FOUND) return; NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4); NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); } if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel)) { AsicSwitchChannel(pAd, 1, FALSE); AsicLockChannel(pAd, 1); LinkDown(pAd, FALSE); MlmeQueueInit(&pAd->Mlme.Queue); BssTableInit(&pAd->ScanTab); RTMPusecDelay(1000000); for (index = 0 ; index < pAd->ChannelListNum; index++) { if (pAd->ChannelList[index].Channel == NewChannel) { pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel; pAd->CommonCfg.Channel = NewChannel; AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.Channel); DBGPRINT(RT_DEBUG_TRACE, ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel)); break; } } if (index >= pAd->ChannelListNum) { DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum)); } } if ((! is_my_bssid) && ADHOC_ON(pAd)) { INT i; if (pAd->StaCfg.WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus) { return; } for (i = 0; i < 6; i++) { if (Bssid[i] > pAd->CommonCfg.Bssid[i]) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5])); AsicDisableSync(pAd); COPY_MAC_ADDR(pAd->CommonCfg.Bssid, Bssid); AsicSetBssid(pAd, pAd->CommonCfg.Bssid); MakeIbssBeacon(pAd); AsicEnableIbssSync(pAd); is_my_bssid = TRUE; break; } else if (Bssid[i] < pAd->CommonCfg.Bssid[i]) break; } } NdisGetSystemUpTime(&Now); pBss = &pAd->ScanTab.BssEntry[Bssidx]; pBss->Rssi = RealRssi; pBss->LastBeaconRxTime = Now; if (is_my_bssid) { RXWI_STRUC RxWI; pAd->StaCfg.DtimCount = DtimCount; pAd->StaCfg.DtimPeriod = DtimPeriod; pAd->StaCfg.LastBeaconRxTime = Now; RxWI.RSSI0 = Elem->Rssi0; RxWI.RSSI1 = Elem->Rssi1; RxWI.RSSI2 = Elem->Rssi2; Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI); if (AironetCellPowerLimit != 0xFF) { ChangeToCellPowerLimit(pAd, AironetCellPowerLimit); } else { pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; } if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo))) { UCHAR MaxSupportedRateIn500Kbps = 0; UCHAR idx; MAC_TABLE_ENTRY *pEntry; for (idx=0; idx<SupRateLen; idx++) { if (MaxSupportedRateIn500Kbps < (SupRate[idx] & 0x7f)) MaxSupportedRateIn500Kbps = SupRate[idx] & 0x7f; } for (idx=0; idx<ExtRateLen; idx++) { if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f)) MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f; } pEntry = MacTableLookup(pAd, Addr2); if ((ADHOC_ON(pAd) && (Elem->Wcid == RESERVED_WCID)) || (pEntry && ((pEntry->LastBeaconRxTime + ADHOC_ENTRY_BEACON_LOST_TIME) < Now))) { if (pEntry == NULL) pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE); if (StaAddMacTableEntry(pAd, pEntry, MaxSupportedRateIn500Kbps, &HtCapability, HtCapabilityLen, &AddHtInfo, AddHtInfoLen, CapabilityInfo) == FALSE) { DBGPRINT(RT_DEBUG_TRACE, ("ADHOC - Add Entry failed.\n")); return; } if (pEntry && (Elem->Wcid == RESERVED_WCID)) { idx = pAd->StaCfg.DefaultKeyId; RTMP_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry); } } if (pEntry && pEntry->ValidAsCLI) pEntry->LastBeaconRxTime = Now; if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); pAd->IndicateMediaState = NdisMediaStateConnected; RTMP_IndicateMediaState(pAd); pAd->ExtraInfo = GENERAL_LINK_UP; AsicSetBssid(pAd, pAd->CommonCfg.Bssid); Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel); if (Bssidx == BSS_NOT_FOUND) { Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod, &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability, &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0, &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE); } DBGPRINT(RT_DEBUG_TRACE, ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n")); } } if (INFRA_ON(pAd)) { BOOLEAN bUseShortSlot, bUseBGProtection; bUseShortSlot = CAP_IS_SHORT_SLOT(CapabilityInfo); if (bUseShortSlot != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED)) AsicSetSlotTime(pAd, bUseShortSlot); bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(Erp)); if (pAd->CommonCfg.Channel > 14) bUseBGProtection = FALSE; if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) { if (bUseBGProtection) { OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),FALSE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)); } else { OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),TRUE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)); } DBGPRINT(RT_DEBUG_WARN, ("SYNC - AP changed B/G protection to %d\n", bUseBGProtection)); } #ifdef DOT11_N_SUPPORT if ((AddHtInfoLen != 0) && ((AddHtInfo.AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) || (AddHtInfo.AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent))) { pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = AddHtInfo.AddHtInfo2.NonGfPresent; pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = AddHtInfo.AddHtInfo2.OperaionMode; if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1) { AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE); } else AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP changed N OperaionMode to %d\n", pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode)); } #endif if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) && ERP_IS_USE_BARKER_PREAMBLE(Erp)) { MlmeSetTxPreamble(pAd, Rt802_11PreambleLong); DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP forced to use LONG preamble\n")); } if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && (EdcaParm.bValid == TRUE) && (EdcaParm.EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount)) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n", pAd->CommonCfg.APEdcaParm.EdcaUpdateCount, EdcaParm.EdcaUpdateCount)); AsicSetEdcaParm(pAd, &EdcaParm); } NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM)); NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM)); } if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) || (pAd->CommonCfg.bAPSDForcePowerSave)) { UCHAR FreeNumber; if (MessageToMe) { #ifdef RTMP_MAC_PCI if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { if (pAd->Antenna.field.RxPath > 1) RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); } #endif if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && pAd->CommonCfg.bAPSDAC_BE && pAd->CommonCfg.bAPSDAC_BK && pAd->CommonCfg.bAPSDAC_VI && pAd->CommonCfg.bAPSDAC_VO) { pAd->CommonCfg.bNeedSendTriggerFrame = TRUE; } else RTMP_PS_POLL_ENQUEUE(pAd); } else if (BcastFlag && (DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM)) { #ifdef RTMP_MAC_PCI if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { if (pAd->Antenna.field.RxPath > 1) RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); } #endif } else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) || (pAd->TxSwQueue[QID_AC_BE].Number != 0) || (pAd->TxSwQueue[QID_AC_VI].Number != 0) || (pAd->TxSwQueue[QID_AC_VO].Number != 0) || (RTMPFreeTXDRequest(pAd, QID_AC_BK, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || (RTMPFreeTXDRequest(pAd, QID_AC_BE, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || (RTMPFreeTXDRequest(pAd, QID_AC_VI, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || (RTMPFreeTXDRequest(pAd, QID_AC_VO, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) || (RTMPFreeTXDRequest(pAd, QID_MGMT, MGMT_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS)) { #ifdef RTMP_MAC_PCI if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) { if (pAd->Antenna.field.RxPath > 1) RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3); } #endif } else { if ((pAd->CommonCfg.bACMAPSDTr[QID_AC_VO]) || (pAd->CommonCfg.bACMAPSDTr[QID_AC_VI]) || (pAd->CommonCfg.bACMAPSDTr[QID_AC_BK]) || (pAd->CommonCfg.bACMAPSDTr[QID_AC_BE])) { } else { USHORT NextDtim = DtimCount; if (NextDtim == 0) NextDtim = DtimPeriod; TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) TbttNumToNextWakeUp = NextDtim; if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { pAd->ThisTbttNumToNextWakeUp = TbttNumToNextWakeUp; AsicSleepThenAutoWakeup(pAd, pAd->ThisTbttNumToNextWakeUp); } } } } } } }