📄 rtusb_data.c
字号:
*pDestTxD = TxD;
pTxD = pDestTxD;
#endif
RTUSBWriteTxDescriptor(pAd, pTxD, CIPHER_NONE, 0,0, AckRequired, FALSE, FALSE, SHORT_RETRY,
IFS_BACKOFF, MlmeRate, /*Length+4*/ Length, QueIdx, PID_MGMT_FRAME, FALSE);
// Build our URB for USBD
TransferBufferLength = sizeof(TXD_STRUC) + Length;
if ((TransferBufferLength % 2) == 1)
TransferBufferLength++;
if ((TransferBufferLength % pAd->BulkOutMaxPacketSize) == 0)
TransferBufferLength += 2;
pMLMEContext->BulkOutSize = TransferBufferLength;
RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
DBGPRINT(RT_DEBUG_INFO, "<---MlmeHardTransmit\n");
}
/*
========================================================================
Routine Description:
This subroutine will scan through releative ring descriptor to find
out avaliable free ring descriptor and compare with request size.
Arguments:
pAd Pointer to our adapter
RingType Selected Ring
Return Value:
NDIS_STATUS_FAILURE Not enough free descriptor
NDIS_STATUS_SUCCESS Enough free descriptor
Note:
========================================================================
*/
NDIS_STATUS RTUSBFreeDescriptorRequest(
IN PRTMP_ADAPTER pAd,
IN UCHAR RingType,
IN UCHAR BulkOutPipeId,
IN UCHAR NumberRequired)
{
UCHAR FreeNumber = 0;
UINT Index;
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
switch (RingType)
{
case TX_RING:
Index = (pAd->NextTxIndex[BulkOutPipeId] + 1) % TX_RING_SIZE;
do
{
PTX_CONTEXT pTxD = &pAd->TxContext[BulkOutPipeId][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 = pAd->NextMLMEIndex;
do
{
PTX_CONTEXT pTxD = &pAd->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:
DBGPRINT_RAW(RT_DEBUG_ERROR, "--->RTUSBFreeDescriptorRequest() -----!! \n");
break;
}
return (Status);
}
/*
========================================================================
Routine Description:
Arguments:
Return Value:
Note:
========================================================================
*/
VOID RTUSBRejectPendingPackets(
IN PRTMP_ADAPTER pAd)
{
UCHAR Index;
PQUEUE_HEADER pQueue;
struct sk_buff *skb;
ULONG IrqFlags;
DBGPRINT_RAW(RT_DEBUG_TRACE, "--->RejectPendingPackets\n");
for (Index = 0; Index < 4; Index++)
{
NdisAcquireSpinLock(&pAd->SendTxWaitQueueLock[Index], IrqFlags);
while (pAd->SendTxWaitQueue[Index].Head != NULL)
{
pQueue = (PQUEUE_HEADER) &(pAd->SendTxWaitQueue[Index]);
skb = (struct sk_buff *)RemoveHeadQueue(pQueue);
RTUSBFreeSkbBuffer(skb);
}
NdisReleaseSpinLock(&pAd->SendTxWaitQueueLock[Index], IrqFlags);
}
DBGPRINT_RAW(RT_DEBUG_TRACE, "<---RejectPendingPackets\n");
}
/*
========================================================================
Routine Description:
Calculates the duration which is required to transmit out frames
with given size and specified rate.
Arguments:
pTxD Pointer to transmit descriptor
Ack Setting for Ack requirement bit
Fragment Setting for Fragment bit
RetryMode Setting for retry mode
Ifs Setting for IFS gap
Rate Setting for transmit rate
Service Setting for service
Length Frame length
TxPreamble Short or Long preamble when using CCK rates
QueIdx - 0-3, according to 802.11e/d4.4 June/2003
Return Value:
None
========================================================================
*/
VOID RTUSBWriteTxDescriptor(
IN PRTMP_ADAPTER pAd,
IN PTXD_STRUC pSourceTxD,
IN UCHAR CipherAlg,
IN UCHAR KeyTable,
IN UCHAR KeyIdx,
IN BOOLEAN Ack,
IN BOOLEAN Fragment,
IN BOOLEAN InsTimestamp,
IN UCHAR RetryMode,
IN UCHAR Ifs,
IN UINT Rate,
IN ULONG Length,
IN UCHAR QueIdx,
IN UCHAR PID,
IN BOOLEAN bAfterRTSCTS)
{
UINT Residual;
PTXD_STRUC pTxD;
#ifndef BIG_ENDIAN
pTxD = pSourceTxD;
#else
TXD_STRUC TxD;
TxD = *pSourceTxD;
pTxD = &TxD;
RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
#endif
pTxD->HostQId = QueIdx;
pTxD->MoreFrag = Fragment;
pTxD->ACK = Ack;
pTxD->Timestamp = InsTimestamp;
pTxD->RetryMd = RetryMode;
pTxD->Ofdm = (Rate < RATE_FIRST_OFDM_RATE)? 0:1;
pTxD->IFS = Ifs;
pTxD->PktId = PID;
pTxD->Drop = 1; // 1:valid, 0:drop
pTxD->HwSeq = 1; // (QueIdx == QID_MGMT)? 1:0;
pTxD->BbpTxPower = DEFAULT_BBP_TX_POWER; // TODO: to be modified
pTxD->DataByteCnt = Length;
RTMPCckBbpTuning(pAd, Rate);
// fill encryption related information, if required
pTxD->CipherAlg = CipherAlg;
if (CipherAlg != CIPHER_NONE)
{
pTxD->KeyTable = KeyTable;
pTxD->KeyIndex = KeyIdx;
pTxD->TkipMic = 1;
}
// In TKIP+fragmentation. TKIP MIC is already appended by driver. MAC needs not generate MIC
if (CipherAlg == CIPHER_TKIP_NO_MIC)
{
pTxD->CipherAlg = CIPHER_TKIP;
pTxD->TkipMic = 0; // tell MAC need not insert TKIP MIC
}
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
{
if ((pAd->PortCfg.APEdcaParm.bValid) && (QueIdx <= QID_AC_VO))
{
pTxD->Cwmin = pAd->PortCfg.APEdcaParm.Cwmin[QueIdx];
pTxD->Cwmax = pAd->PortCfg.APEdcaParm.Cwmax[QueIdx];
pTxD->Aifsn = pAd->PortCfg.APEdcaParm.Aifsn[QueIdx];
}
else
{
DBGPRINT(RT_DEBUG_ERROR," WMM in used but EDCA not valid ERROR !!\n)");
}
}
else
{
if (bAfterRTSCTS)
{
// After RTS/CTS frame, data frame should use SIFS time.
// To patch this code, add the following code.
// Recommended by Jerry 2005/07/25 for WiFi testing with Proxim AP
pTxD->Cwmin = 0;
pTxD->Cwmax = 0;
pTxD->Aifsn = 1;
pTxD->IFS = IFS_BACKOFF;
}
else
{
pTxD->Cwmin = CW_MIN_IN_BITS;
pTxD->Cwmax = CW_MAX_IN_BITS;
pTxD->Aifsn = 2;
}
}
// fill up PLCP SIGNAL field
pTxD->PlcpSignal = RateIdToPlcpSignal[Rate];
if (((Rate == RATE_2) || (Rate == RATE_5_5) || (Rate == RATE_11)) &&
(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)))
{
pTxD->PlcpSignal |= 0x0008;
}
// fill up PLCP SERVICE field, not used for OFDM rates
pTxD->PlcpService = 4; // Service;
// file up PLCP LENGTH_LOW and LENGTH_HIGH fields
Length += LENGTH_CRC; // CRC length
switch (CipherAlg)
{
case CIPHER_WEP64: Length += 8; break; // IV + ICV
case CIPHER_WEP128: Length += 8; break; // IV + ICV
case CIPHER_TKIP: Length += 20; break; // IV + EIV + MIC + ICV
case CIPHER_AES: Length += 16; break; // IV + EIV + MIC
case CIPHER_CKIP64: Length += 8; break; // IV + CMIC + ICV, but CMIC already inserted by driver
case CIPHER_CKIP128: Length += 8; break; // IV + CMIC + ICV, but CMIC already inserted by driver
case CIPHER_TKIP_NO_MIC: Length += 12; break; // IV + EIV + ICV
default: break;
}
if (Rate < RATE_FIRST_OFDM_RATE) // 11b - RATE_1, RATE_2, RATE_5_5, RATE_11
{
if ((Rate == RATE_1) || ( Rate == RATE_2))
{
Length = Length * 8 / (Rate + 1);
}
else
{
Residual = ((Length * 16) % (11 * (1 + Rate - RATE_5_5)));
Length = Length * 16 / (11 * (1 + Rate - RATE_5_5));
if (Residual != 0)
{
Length++;
}
if ((Residual <= (3 * (1 + Rate - RATE_5_5))) && (Residual != 0))
{
if (Rate == RATE_11) // Only 11Mbps require length extension bit
pTxD->PlcpService |= 0x80; // 11b's PLCP Length extension bit
}
}
pTxD->PlcpLengthHigh = Length >> 8; // 256;
pTxD->PlcpLengthLow = Length % 256;
}
else // OFDM - RATE_6, RATE_9, RATE_12, RATE_18, RATE_24, RATE_36, RATE_48, RATE_54
{
pTxD->PlcpLengthHigh = Length >> 6; // 64; // high 6-bit of total byte count
pTxD->PlcpLengthLow = Length % 64; // low 6-bit of total byte count
}
pTxD->Burst = Fragment;
pTxD->Burst2 = pTxD->Burst;
#ifdef BIG_ENDIAN
RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
WriteBackToDescriptor((PUCHAR)pSourceTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
#endif
}
/*
========================================================================
Routine Description:
To do the enqueue operation and extract the first item of waiting
list. If a number of available shared memory segments could meet
the request of extracted item, the extracted item will be fragmented
into shared memory segments.
Arguments:
pAd Pointer to our adapter
pQueue Pointer to Waiting Queue
Return Value:
None
Note:
========================================================================
*/
VOID RTMPDeQueuePacket(
IN PRTMP_ADAPTER pAd,
IN UCHAR BulkOutPipeId)
{
struct sk_buff *pSkb;
UCHAR FragmentRequired;
NDIS_STATUS Status;
UCHAR Count = 0;
PQUEUE_HEADER pQueue;
UCHAR QueIdx;
ULONG IrqFlags;
NdisAcquireSpinLock(&pAd->DeQueueLock[BulkOutPipeId], IrqFlags);
if (pAd->DeQueueRunning[BulkOutPipeId])
{
NdisReleaseSpinLock(&pAd->DeQueueLock[BulkOutPipeId], IrqFlags);
return;
}
else
{
pAd->DeQueueRunning[BulkOutPipeId] = TRUE;
NdisReleaseSpinLock(&pAd->DeQueueLock[BulkOutPipeId], IrqFlags);
}
QueIdx = BulkOutPipeId;
if (pAd->TxRingTotalNumber[BulkOutPipeId])
DBGPRINT(RT_DEBUG_INFO,"--RTMPDeQueuePacket %d TxRingTotalNumber= %d !!--\n", BulkOutPipeId, (INT)pAd->TxRingTotalNumber[BulkOutPipeId]);
// Make sure SendTxWait queue resource won't be used by other threads
NdisAcquireSpinLock(&pAd->SendTxWaitQueueLock[BulkOutPipeId], IrqFlags);
// Select Queue
pQueue = &pAd->SendTxWaitQueue[BulkOutPipeId];
// Check queue before dequeue
while ((pQueue->Head != NULL) && (Count < MAX_TX_PROCESS))
{
// Reset is in progress, stop immediately
if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
{
DBGPRINT(RT_DEBUG_ERROR,"--RTMPDeQueuePacket %d reset-in-progress !!--\n", BulkOutPipeId);
break;
}
// Dequeue the first entry from head of queue list
pSkb = (struct sk_buff*)RemoveHeadQueue(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(pSkb) + RTMP_GET_PACKET_RTS(pSkb);
if ((RTUSBFreeDescriptorRequest(pAd, TX_RING, BulkOutPipeId, FragmentRequired) == NDIS_STATUS_SUCCESS))
{
// Avaliable ring descriptors are enough for this frame
// Call hard transmit
// Nitro mode / Normal mode selection
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -