📄 rtusb_data.c
字号:
/*************************************************************************** * RT2x00 SourceForge Project - http://rt2x00.sourceforge.net * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * Licensed under the GNU GPL * * Original code supplied under license from RaLink Inc, 2004. * ***************************************************************************//*************************************************************************** * Module Name: rtusb_data.c * * Abstract: * * Revision History: * Who When What * -------- ---------- ------------------------------- * Name Date Modification logs * Jan Lee 2005-06-01 Release * RobinC 02-06-2005 RFMON Mode added * MathiasK 04-07-2005 big endian fix from gglomm ***************************************************************************/#include "rt_config.h"static UCHAR PlcpSignal[12] = { 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14static UINT _11G_RATES[12] = { 0, 0, 0, 0, 6, 9, 12, 18, 24, 36, 48, 54 };static UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};static UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};static UCHAR EAPOL[] = {0x88, 0x8e};static UCHAR IPX[] = {0x81, 0x37};static UCHAR APPLE_TALK[] = {0x80, 0xf3};UCHAR ARP[]={0x08, 0x06};//////////////////////////////////////////////////////////////////////////////// FUNCTION// RTUSBSendPackets// // DESCRIPTION// VNETMultipleSend handler is called by NDIS to transmit packets// through the adapter. If there are packets in the Q and the device// can accept the Tx requests initiate a transmission and queue the// rest of the packets (if any...). If we can not transmit or the// station is not ready we imediatelly complete the request// // INPUT// MiniportAdapterContext Context registered with the wrapper// (Ptr to to the Adapter object)// PacketArray Array of Ptrs to NDIS_PACKET structs// NumberOfPackets Number of packets in PacketArray// // OUTPUT// -// ////////////////////////////////////////////////////////////////////////////int RTUSBSendPackets(struct sk_buff *skb, struct net_device *net_dev){ NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PRT2570ADAPTER pAdapter = net_dev->priv; skb->data_len = skb->len; if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RESET_IN_PROGRESS) || RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_REMOVE_IN_PROGRESS) || RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RADIO_OFF) || RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_HALT_IN_PROGRESS)) { RTUSBFreeSkbBuffer(skb); return 0; } // Drop packets if no associations else if (!INFRA_ON(pAdapter) && !ADHOC_ON(pAdapter) && !( pAdapter->PortCfg.BssType == BSS_MONITOR && pAdapter->PortCfg.MallowRFMONTx == TRUE ) ) { RTUSBFreeSkbBuffer(skb); return 0; } else { Status = RTUSBSendPacket(pAdapter, skb); if (Status != NDIS_STATUS_SUCCESS) { // Errors before enqueue stage RTUSBFreeSkbBuffer(skb); DBGPRINT(RT_DEBUG_TRACE,"<---RTUSBSendPackets not dequeue\n"); return 0; } } // Dequeue one frame from SendTxWait queue and process it // There are two place calling dequeue for TX ring. // 1. Here, right after queueing the frame. // 2. At the end of TxRingTxDone service routine. if ((!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RADIO_OFF)) && (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_REMOVE_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { //RTMPDeQueuePacket(pAdapter, &pAdapter->TxSwQueue0); // Call dequeue without selected queue, let the subroutine select the right priority // Tx software queue RTUSBDeQueuePacket(pAdapter); } // Kick bulk out RTUSBKickBulkOut(pAdapter); return 0;}NDIS_STATUS RTUSBSendPacket( IN PRT2570ADAPTER pAdapter, IN struct sk_buff *skb){ PVOID pVirtualAddress; struct sk_buff_head *pTxQueue; ULONG Priority; UCHAR NumberOfFrag; UCHAR RTSRequired; UINT AllowFragSize; UCHAR AccessCategory; NDIS_STATUS Status = NDIS_STATUS_FAILURE; UCHAR PsMode; // Init priority value Priority = 0; AccessCategory = 0; if (skb && pAdapter->PortCfg.BssType == BSS_MONITOR && pAdapter->PortCfg.MallowRFMONTx == TRUE) { NdisAcquireSpinLock(&pAdapter->SendTxWaitQueueLock); skb_queue_tail(&pAdapter->SendTxWaitQueue, skb); NdisReleaseSpinLock(&pAdapter->SendTxWaitQueueLock); return (NDIS_STATUS_SUCCESS); } if (skb) { Priority = skb->priority; // 802.11e/d4.4 June, 2003 if (Priority <=2) AccessCategory = 0; else if (Priority == 3) AccessCategory = 1; else if (Priority <= 5) AccessCategory = 2; else AccessCategory = 3; DBGPRINT(RT_DEBUG_INFO, "Priority = %d, AC = %d\n", Priority, AccessCategory); } // For TKIP, MIC value is treated as payload, it might be fragmented through // different MPDUs. if (pAdapter->PortCfg.WepStatus == Ndis802_11Encryption2Enabled) { skb->data_len += 8; } pVirtualAddress = (PVOID)skb->data; // Check for virtual address allocation, it might fail !!! if (pVirtualAddress == NULL) { DBGPRINT(RT_DEBUG_TRACE,"<---RTUSBSendPacket NULL pVirtualAddress\n"); // Resourece is low, system did not allocation virtual address // return NDIS_STATUS_FAILURE directly to upper layer return (Status); } // // Check for multicast or broadcast (First byte of DA) // if ((*((PUCHAR) pVirtualAddress) & 0x01) != 0) { // For multicast & broadcast, there is no fragment allowed NumberOfFrag = 1; } else { // Check for payload allowed for each fragment AllowFragSize = (pAdapter->PortCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; // Calculate fragments required NumberOfFrag = ((skb->data_len - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1; // Minus 1 if the size just match to allowable fragment size if (((skb->data_len - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0) { NumberOfFrag--; } } // Check for requirement of RTS if (NumberOfFrag > 1) { // If multiple fragment required, RTS is required only for the first fragment // if the fragment size large than RTS threshold RTSRequired = (pAdapter->PortCfg.FragmentThreshold > pAdapter->PortCfg.RtsThreshold) ? 1 : 0; } else { RTSRequired = (skb->data_len > pAdapter->PortCfg.RtsThreshold) ? 1 : 0; } // RTS/CTS may also be required in order to protect OFDM frame if ((pAdapter->PortCfg.TxRate >= RATE_FIRST_OFDM_RATE) && pAdapter->PortCfg.BGProtectionInUsed) RTSRequired = 1; //DBGPRINT(RT_DEBUG_TEMP, "Number of fragments :%d , include RTS :%d\n", NumberOfFrag, NumberOfFrag + RTSRequired); // Save framnet number to Ndis packet reserved field RTMP_SET_PACKET_FRAGMENTS(skb, NumberOfFrag); // Save RTS requirement to Ndis packet reserved field RTMP_SET_PACKET_RTS(skb, RTSRequired); // Make sure SendTxWait queue resource won't be used by other threads NdisAcquireSpinLock(&pAdapter->SendTxWaitQueueLock); pTxQueue = &pAdapter->SendTxWaitQueue; if (INFRA_ON(pAdapter)) { // In infrastructure mode, simply enqueue the packet into Tx waiting queue. DBGPRINT(RT_DEBUG_INFO, "Infrastructure -> Enqueue one frame\n"); // Enqueue Ndis packet to end of Tx wait queue skb_queue_tail(pTxQueue, skb); Status = NDIS_STATUS_SUCCESS; } else { // In IBSS mode, power state of destination should be considered. PsMode = PWR_ACTIVE; // Faked if (PsMode == PWR_ACTIVE) { // Enqueue Ndis packet to end of Tx wait queue skb_queue_tail(pTxQueue, skb); Status = NDIS_STATUS_SUCCESS; } } NdisReleaseSpinLock(&pAdapter->SendTxWaitQueueLock); return Status;}VOID RTUSBDeQueuePacket( IN PRT2570ADAPTER pAdapter){ UCHAR FragmentRequired; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; struct sk_buff *skb; struct sk_buff_head *pQueue; UCHAR Count = 0; // Make sure SendTxWait queue resource won't be used by other threads NdisAcquireSpinLock(&pAdapter->SendTxWaitQueueLock); // Select Queue pQueue = &pAdapter->SendTxWaitQueue; // Check queue before dequeue while (!skb_queue_empty(pQueue) && (Count < MAX_TX_PROCESS)) { // Reset is in progress, stop immediately if ( RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_RESET_IN_PROGRESS) || RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_REMOVE_IN_PROGRESS) || RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_HALT_IN_PROGRESS)) { break; } // Dequeue the first entry from head of queue list skb = skb_dequeue(pQueue); // RTS or CTS-to-self for B/G protection mode has been set already. // There is no need to re-do it here. // Total fragment required = number of fragment + RST if required FragmentRequired = RTMP_GET_PACKET_FRAGMENTS(skb) + RTMP_GET_PACKET_RTS(skb); if (RTUSBFreeDescriptorRequest(pAdapter, TX_RING, FragmentRequired) == NDIS_STATUS_SUCCESS) { // Avaliable ring descriptors are enough for this frame // Call hard transmit // Nitro mode / Normal mode selection NdisReleaseSpinLock(&pAdapter->SendTxWaitQueueLock); if (pAdapter->PortCfg.EnableTxBurst == 1) Status = RTUSBHardEncrypt(pAdapter, skb, FragmentRequired, TRUE); else Status = RTUSBHardEncrypt(pAdapter, skb, FragmentRequired, FALSE); // // Acquire the resource again, snice we may need to process it in this while-loop. // NdisAcquireSpinLock(&pAdapter->SendTxWaitQueueLock); if (Status == NDIS_STATUS_FAILURE) { // Packet failed due to various Ndis Packet error RTUSBFreeSkbBuffer(skb); break; } else if (Status == NDIS_STATUS_RESOURCES) { // Not enough free tx ring, it might happen due to free descriptor inquery might be not correct // It also might change to NDIS_STATUS_FAILURE to simply drop the frame // Put the frame back into head of queue skb_queue_head(pQueue, skb); break; } Count++; } else { skb_queue_head(pQueue, skb); break; } } NdisReleaseSpinLock(&pAdapter->SendTxWaitQueueLock); return; }NDIS_STATUS RTUSBFreeDescriptorRequest( IN PRT2570ADAPTER pAdapter, IN UCHAR RingType, IN UCHAR NumberRequired){ UCHAR FreeNumber = 0; UINT Index; NDIS_STATUS Status = NDIS_STATUS_FAILURE; switch (RingType) { case TX_RING: Index = pAdapter->NextTxIndex; do { PTX_CONTEXT pTxD = &pAdapter->TxContext[Index]; // While Owner bit is NIC, obviously ASIC still need it. // If valid bit is TRUE, indicate that TxDone has not process yet // We should not use it until TxDone finish cleanup job if (pTxD->InUse == FALSE) { // This one is free FreeNumber++; } else { break; } Index = (Index + 1) % TX_RING_SIZE; } while (FreeNumber < NumberRequired); // Quit here ! Free number is enough ! if (FreeNumber >= NumberRequired) { Status = NDIS_STATUS_SUCCESS; } break; case PRIO_RING: Index = pAdapter->NextMLMEIndex; do { PTX_CONTEXT pTxD = &pAdapter->MLMEContext[Index]; // While Owner bit is NIC, obviously ASIC still need it. // If valid bit is TRUE, indicate that TxDone has not process yet // We should not use it until TxDone finish cleanup job if (pTxD->InUse == FALSE) { // This one is free FreeNumber++; } else { break; } Index = (Index + 1) % PRIO_RING_SIZE; } while (FreeNumber < NumberRequired); // Quit here ! Free number is enough ! if (FreeNumber >= NumberRequired) { Status = NDIS_STATUS_SUCCESS; } break; default: break; } return (Status);}/* ======================================================================== Routine Description: Arguments: Return Value: IRQL =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -