📄 rtmp_data.c
字号:
if (pHeader->FC.MoreFrag) { // release packet RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); return; } // Filter out Bcast frame which AP relayed for us if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) { // release packet RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); return; } Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); DBGPRINT_RAW(RT_DEBUG_INFO, ("!!! report BCAST DATA to LLC (len=%d) !!!\n", pRxBlk->DataSize)); return; } else if (pRxD->U2M) { // Send PS-Poll for AP to send next data frame // if ((pHeader->FC.MoreData) && INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) // EnqueuePsPoll(pAd); pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ; Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI); pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0); pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1); pAd->RalinkCounters.OneSecRxOkDataCnt++; if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0))) { // re-assemble the fragmented packets // return complete frame (pRxPacket) or NULL bFragment = TRUE; pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk); } if (pRxPacket) { pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; // process complete frame if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled)) { // For TKIP frame, calculate the MIC value if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE) { return; } } STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID); return; } else { // just return // because RTMPDeFragmentDataFrame() will release rx packet, // if packet is fragmented return; } } ASSERT(0); // release packet RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);}VOID STAHandleRxMgmtFrame( IN PRTMP_ADAPTER pAd, IN RX_BLK *pRxBlk){ PRXD_STRUC pRxD = &(pRxBlk->RxD); PRXWI_STRUC pRxWI = pRxBlk->pRxWI; PHEADER_802_11 pHeader = pRxBlk->pHeader; PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal); RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);}VOID STAHandleRxControlFrame( IN PRTMP_ADAPTER pAd, IN RX_BLK *pRxBlk){ PRXWI_STRUC pRxWI = pRxBlk->pRxWI; PHEADER_802_11 pHeader = pRxBlk->pHeader; PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; switch (pHeader->FC.SubType) { case SUBTYPE_BLOCK_ACK_REQ: { CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader); } break; case SUBTYPE_BLOCK_ACK: case SUBTYPE_ACK: default: DBGPRINT(RT_DEBUG_INFO,("ignore CNTL (subtype=%d)\n", pHeader->FC.SubType)); break; } RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);}/* ======================================================================== Routine Description: Process RxDone interrupt, running in DPC level Arguments: pAd Pointer to our adapter Return Value: None IRQL = DISPATCH_LEVEL Note: This routine has to maintain Rx ring read pointer. Need to consider QOS DATA format when converting to 802.3 ========================================================================*/BOOLEAN STARxDoneInterruptHandle( IN PRTMP_ADAPTER pAd) { UINT32 RxProcessed, RxPending; BOOLEAN bReschedule = FALSE; RXD_STRUC *pRxD; UCHAR *pData; PRXWI_STRUC pRxWI; PNDIS_PACKET pRxPacket; PHEADER_802_11 pHeader; RX_BLK RxCell; RxProcessed = RxPending = 0; // process whole rx ring while (1) { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS) || !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP)) { break; } if (RxProcessed++ > MAX_RX_PROCESS_CNT) { // need to reschedule rx handle bReschedule = TRUE; break; } // 1. allocate a new data packet into rx ring to replace received packet // then processing the received packet // 2. the callee must take charge of release of packet // 3. As far as driver is concerned , // the rx packet must // a. be indicated to upper layer or // b. be released if it is discarded pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending); if (pRxPacket == NULL) { // no more packet to process break; } // get rx ring descriptor pRxD = &(RxCell.RxD); // get rx data buffer pData = GET_OS_PKT_DATAPTR(pRxPacket); pRxWI = (PRXWI_STRUC) pData; pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;#ifdef BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE); RTMPWIEndianChange((PUCHAR)pRxWI, TYPE_RXWI);#endif // build RxCell RxCell.pRxWI = pRxWI; RxCell.pHeader = pHeader; RxCell.pRxPacket = pRxPacket; RxCell.pData = (UCHAR *) pHeader; RxCell.DataSize = pRxWI->MPDUtotalByteCount; RxCell.Flags = 0; // Increase Total receive byte counter after real data received no mater any error or not pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount; pAd->RalinkCounters.RxCount ++; INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount); if (MONITOR_ON(pAd)) { send_monitor_packets(pAd, &RxCell); //RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); break; }#ifdef RALINK_ATE if (pAd->ate.Mode != ATE_STOP) { pAd->ate.RxCntPerSec++; ATESampleRssi(pAd, pRxWI);#ifdef RALINK_2860_QA if (pAd->ate.bQARxStart == TRUE) { ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader); }#endif // RALINK_2860_QA // RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); continue; }#endif // RALINK_ATE // // Check for all RxD errors if (RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD) != NDIS_STATUS_SUCCESS) { pAd->Counters8023.RxErrors++; // discard this frame RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); continue; } switch (pHeader->FC.Type) { // CASE I, receive a DATA frame case BTYPE_DATA: { // process DATA frame STAHandleRxDataFrame(pAd, &RxCell); } break; // CASE II, receive a MGMT frame case BTYPE_MGMT: { STAHandleRxMgmtFrame(pAd, &RxCell); } break; // CASE III. receive a CNTL frame case BTYPE_CNTL: { STAHandleRxControlFrame(pAd, &RxCell); } break; // discard other type default: RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); break; } } return bReschedule;}/* ======================================================================== Routine Description: Process TxDone interrupt, running in DPC level Arguments: Adapter Pointer to our adapter Return Value: None IRQL = DISPATCH_LEVEL Note: ========================================================================*/VOID RTMPHandleTxDoneInterrupt( IN PRTMP_ADAPTER pAd){}// this portion already move to cmm_data.c// RTMPHandleTxRingDmaDoneInterrupt,// RTMPHandleMgmtRingDmaDoneInterrupt,// RTMPHandleTBTTInterrupt,// RTMPHandlePreTBTTInterrupt// move to cmm_data.c/* ======================================================================== Routine Description: Arguments: pAd Pointer to our adapter IRQL = DISPATCH_LEVEL ========================================================================*/VOID RTMPHandleTwakeupInterrupt( IN PRTMP_ADAPTER pAd){ DBGPRINT(RT_DEBUG_INFO, ("Twakeup Expired... !!!\n")); AsicForceWakeup(pAd);}// this portion already move to cmm_data.c// RTMPHandleRxCoherentInterrupt,// MiniportMMRequest,// MlmeHardTransmit,// TxFrameIsAggregatible,// Sniff2BytesFromNdisBuffer,// RTMPDeQueuePacket/* ======================================================================== Routine Description: This routine classifies outgoing frames into several AC (Access Category) and enqueue them into corresponding s/w waiting queues. Arguments: pAd Pointer to our adapter pPacket Pointer to send packet Return Value: None IRQL = DISPATCH_LEVEL Note: ========================================================================*/NDIS_STATUS RTMPSendPacket( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket){ PACKET_INFO PacketInfo; PUCHAR pSrcBufVA; UINT SrcBufLen; UINT AllowFragSize; UCHAR NumberOfFrag;// UCHAR RTSRequired; UCHAR QueIdx, UserPriority; // Prepare packet information structure for buffer descriptor // chained within a single NDIS packet. RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); if (pSrcBufVA == NULL) { DBGPRINT(RT_DEBUG_ERROR,("RTMPSendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen)); // Resourece is low, system did not allocate virtual address // return NDIS_STATUS_FAILURE directly to upper layer RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return NDIS_STATUS_FAILURE; } DBGPRINT(RT_DEBUG_LOUD,("RTMPSendPacket --> pSrcBufVA == %p, SrcBufLen=%d\n", pSrcBufVA, SrcBufLen)); // STEP 1. Decide number of fragments required to deliver this MSDU. // The estimation here is not very accurate because difficult to // take encryption overhead into consideration here. The result // "NumberOfFrag" is then just used to pre-check if enough free // TXD are available to hold this MSDU. if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast NumberOfFrag = 1; else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)) NumberOfFrag = 1; // Aggregation overwhelms fragmentation else if (CLIENT_STATUS_TEST_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_AMSDU_INUSED)) NumberOfFrag = 1; // Aggregation overwhelms fragmentation else if ((pAd->CommonCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->CommonCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD)) NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation else { // The calculated "NumberOfFrag" is a rough estimation because of various // encryption/encapsulation overhead not taken into consideration. This number is just // used to make sure enough free TXD are available before fragmentation takes place. // In case the actual required number of fragments of an NDIS packet // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should // rarely happen and the penalty is just like a TX RETRY fail. Affordable. AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1; // To get accurate number of fragmentation if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0) { NumberOfFrag--; } } // Save fragment number to Ndis packet reserved field RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag); // STEP 2. Check the requirement of RTS: // If multiple fragment required, RTS is required only for the first fragment // if the fragment size large than RTS threshold // Save RTS requirement to Ndis packet reserved field RTMP_SET_PACKET_RTS(pPacket, 0); RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate); // // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx> // UserPriority = 0; QueIdx = QID_AC_BE; if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) { USHORT Protocol; UCHAR LlcSnapLen = 0, Byte0, Byte1; do
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -