2
*************************************************************************
4
* 5F., No.36, Taiyuan St., Jhubei City,
8
* (c) Copyright 2002-2007, Ralink Technology, Inc.
10
* This program is free software; you can redistribute it and/or modify *
11
* it under the terms of the GNU General Public License as published by *
12
* the Free Software Foundation; either version 2 of the License, or *
13
* (at your option) any later version. *
15
* This program is distributed in the hope that it will be useful, *
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18
* GNU General Public License for more details. *
20
* You should have received a copy of the GNU General Public License *
21
* along with this program; if not, write to the *
22
* Free Software Foundation, Inc., *
23
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25
*************************************************************************
29
All functions in this file must be PCI-depended, or you should out your function
33
#include "../rt_config.h"
35
u16 RtmpPCI_WriteTxResource(struct rt_rtmp_adapter *pAd,
36
struct rt_tx_blk *pTxBlk,
37
IN BOOLEAN bIsLast, u16 * FreeNumber)
44
struct rt_rtmp_tx_ring *pTxRing;
48
/* get Tx Ring Resource */
50
pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
51
TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
52
pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
54
RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
56
/* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */
57
if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) {
58
/*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */
60
pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD +
61
pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
63
/*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */
64
hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
66
NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf,
67
TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
69
pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
70
pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
73
/* build Tx Descriptor */
76
pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa;
77
NdisZeroMemory(pTxD, TXD_SIZE);
79
pTxD->SDPtr0 = BufBasePaLow;
80
pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; /* include padding */
81
pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
82
pTxD->SDLen1 = pTxBlk->SrcBufLen;
84
pTxD->LastSec1 = (bIsLast) ? 1 : 0;
86
RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
92
INC_RING_INDEX(TxIdx, TX_RING_SIZE);
93
pTxRing->TxCpuIdx = TxIdx;
100
u16 RtmpPCI_WriteSingleTxResource(struct rt_rtmp_adapter *pAd,
101
struct rt_tx_blk *pTxBlk,
108
struct rt_txd * pTxD;
110
struct rt_rtmp_tx_ring *pTxRing;
114
/* get Tx Ring Resource */
116
pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
117
TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
118
pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
120
RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
122
/* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */
123
/*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */
124
hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
126
NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf,
127
TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
129
pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
130
pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
133
/* build Tx Descriptor */
135
pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa;
136
NdisZeroMemory(pTxD, TXD_SIZE);
138
pTxD->SDPtr0 = BufBasePaLow;
139
pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; /* include padding */
140
pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
141
pTxD->SDLen1 = pTxBlk->SrcBufLen;
143
pTxD->LastSec1 = (bIsLast) ? 1 : 0;
145
RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
149
/* Update Tx index */
151
INC_RING_INDEX(TxIdx, TX_RING_SIZE);
152
pTxRing->TxCpuIdx = TxIdx;
159
u16 RtmpPCI_WriteMultiTxResource(struct rt_rtmp_adapter *pAd,
160
struct rt_tx_blk *pTxBlk,
161
u8 frameNum, u16 * FreeNumber)
166
struct rt_txd * pTxD;
168
struct rt_rtmp_tx_ring *pTxRing;
172
bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0);
175
/* get Tx Ring Resource */
177
pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
178
TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
179
pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
181
RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
184
/* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */
185
if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
186
/*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */
188
pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD +
189
pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
190
else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
191
/*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; */
193
pTxBlk->MpduHeaderLen -
194
LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen +
195
LENGTH_ARALINK_HEADER_FIELD;
197
/*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */
198
hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
200
firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
202
firstDMALen = pTxBlk->MpduHeaderLen;
205
NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
207
pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
208
pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
211
/* build Tx Descriptor */
213
pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa;
214
NdisZeroMemory(pTxD, TXD_SIZE);
216
pTxD->SDPtr0 = BufBasePaLow;
217
pTxD->SDLen0 = firstDMALen; /* include padding */
218
pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
219
pTxD->SDLen1 = pTxBlk->SrcBufLen;
221
pTxD->LastSec1 = (bIsLast) ? 1 : 0;
223
RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
227
/* Update Tx index */
229
INC_RING_INDEX(TxIdx, TX_RING_SIZE);
230
pTxRing->TxCpuIdx = TxIdx;
238
void RtmpPCI_FinalWriteTxResource(struct rt_rtmp_adapter *pAd,
239
struct rt_tx_blk *pTxBlk,
240
u16 totalMPDUSize, u16 FirstTxIdx)
243
struct rt_txwi * pTxWI;
244
struct rt_rtmp_tx_ring *pTxRing;
247
/* get Tx Ring Resource */
249
pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
250
pTxWI = (struct rt_txwi *) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa;
251
pTxWI->MPDUtotalByteCount = totalMPDUSize;
255
void RtmpPCIDataLastTxIdx(struct rt_rtmp_adapter *pAd,
256
u8 QueIdx, u16 LastTxIdx)
258
struct rt_txd * pTxD;
259
struct rt_rtmp_tx_ring *pTxRing;
262
/* get Tx Ring Resource */
264
pTxRing = &pAd->TxRing[QueIdx];
267
/* build Tx Descriptor */
269
pTxD = (struct rt_txd *) pTxRing->Cell[LastTxIdx].AllocVa;
275
u16 RtmpPCI_WriteFragTxResource(struct rt_rtmp_adapter *pAd,
276
struct rt_tx_blk *pTxBlk,
277
u8 fragNum, u16 * FreeNumber)
281
struct rt_txd * pTxD;
283
struct rt_rtmp_tx_ring *pTxRing;
288
/* Get Tx Ring Resource */
290
pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
291
TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
292
pDMAHeaderBufVA = (u8 *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
294
RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
297
/* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */
299
/*hwHeaderLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */
300
hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
302
firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen;
303
NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
306
/* Build Tx Descriptor */
308
pTxD = (struct rt_txd *) pTxRing->Cell[TxIdx].AllocVa;
309
NdisZeroMemory(pTxD, TXD_SIZE);
311
if (fragNum == pTxBlk->TotalFragNum) {
312
pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
313
pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
316
pTxD->SDPtr0 = BufBasePaLow;
317
pTxD->SDLen0 = firstDMALen; /* include padding */
318
pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
319
pTxD->SDLen1 = pTxBlk->SrcBufLen;
323
RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
326
pTxBlk->Priv += pTxBlk->SrcBufLen;
329
/* Update Tx index */
331
INC_RING_INDEX(TxIdx, TX_RING_SIZE);
332
pTxRing->TxCpuIdx = TxIdx;
341
Must be run in Interrupt context
342
This function handle PCI specific TxDesc and cpu index update and kick the packet out.
344
int RtmpPCIMgmtKickOut(struct rt_rtmp_adapter *pAd,
347
u8 *pSrcBufVA, u32 SrcBufLen)
349
struct rt_txd * pTxD;
350
unsigned long SwIdx = pAd->MgmtRing.TxCpuIdx;
352
pTxD = (struct rt_txd *) pAd->MgmtRing.Cell[SwIdx].AllocVa;
354
pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket;
355
pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL;
357
RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT);
363
PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
364
pTxD->SDLen0 = SrcBufLen;
366
/*================================================================== */
367
/* DBGPRINT_RAW(RT_DEBUG_TRACE, ("MLMEHardTransmit\n"));
368
for (i = 0; i < (TXWI_SIZE+24); i++)
371
DBGPRINT_RAW(RT_DEBUG_TRACE, ("%x:", *(pSrcBufVA+i)));
373
DBGPRINT_RAW(RT_DEBUG_TRACE, (" :: "));
375
DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n "));
377
DBGPRINT_RAW(RT_DEBUG_TRACE, ("\n "));*/
378
/*======================================================================= */
380
pAd->RalinkCounters.KickTxCount++;
381
pAd->RalinkCounters.OneSecTxDoneCount++;
383
/* Increase TX_CTX_IDX, but write to register later. */
384
INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
386
RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
392
========================================================================
395
Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
398
pRxD Pointer to the Rx descriptor
401
NDIS_STATUS_SUCCESS No err
402
NDIS_STATUS_FAILURE Error
406
========================================================================
408
int RTMPCheckRxError(struct rt_rtmp_adapter *pAd,
409
struct rt_header_802_11 * pHeader,
410
struct rt_rxwi * pRxWI, IN PRT28XX_RXD_STRUC pRxD)
412
struct rt_cipher_key *pWpaKey;
415
/* Phy errors & CRC errors */
416
if ( /*(pRxD->PhyErr) || */ (pRxD->Crc)) {
417
/* Check RSSI for Noise Hist statistic collection. */
418
dBm = (int)(pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
420
pAd->StaCfg.RPIDensity[0] += 1;
422
pAd->StaCfg.RPIDensity[1] += 1;
424
pAd->StaCfg.RPIDensity[2] += 1;
426
pAd->StaCfg.RPIDensity[3] += 1;
428
pAd->StaCfg.RPIDensity[4] += 1;
430
pAd->StaCfg.RPIDensity[5] += 1;
432
pAd->StaCfg.RPIDensity[6] += 1;
434
pAd->StaCfg.RPIDensity[7] += 1;
436
return (NDIS_STATUS_FAILURE);
438
/* Add Rx size to channel load counter, we should ignore error counts */
439
pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14);
441
/* Drop ToDs promiscuous frame, it is opened due to CCX 2 channel load statistics */
442
if (pHeader != NULL) {
443
if (pHeader->FC.ToDs) {
444
return (NDIS_STATUS_FAILURE);
447
/* Drop not U2M frames, can't drop here because we will drop beacon in this case */
448
/* I am kind of doubting the U2M bit operation */
449
/* if (pRxD->U2M == 0) */
450
/* return(NDIS_STATUS_FAILURE); */
452
/* drop decyption fail frame */
453
if (pRxD->CipherErr) {
454
if (pRxD->CipherErr == 2) {
455
DBGPRINT_RAW(RT_DEBUG_TRACE,
456
("pRxD ERROR: ICV ok but MICErr "));
457
} else if (pRxD->CipherErr == 1) {
458
DBGPRINT_RAW(RT_DEBUG_TRACE, ("pRxD ERROR: ICV Err "));
459
} else if (pRxD->CipherErr == 3)
460
DBGPRINT_RAW(RT_DEBUG_TRACE,
461
("pRxD ERROR: Key not valid "));
463
if (((pRxD->CipherErr & 1) == 1)
464
&& pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
465
RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG,
466
pAd->MacTab.Content[BSSID_WCID].
469
DBGPRINT_RAW(RT_DEBUG_TRACE,
470
(" %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n",
471
pRxD->CipherErr, pRxD->SDL0,
472
pRxD->Mcast | pRxD->Bcast, pRxD->MyBss,
473
pRxWI->WirelessCliID,
474
/* CipherName[pRxD->CipherAlg], */
480
if (pRxD->CipherErr == 2) {
481
pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
482
if (pAd->StaCfg.WpaSupplicantUP)
483
WpaSendMicFailureToWpaSupplicant(pAd,
489
RTMPReportMicError(pAd, pWpaKey);
491
if (((pRxD->CipherErr & 2) == 2)
492
&& pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
493
RTMPSendWirelessEvent(pAd,
494
IW_MIC_ERROR_EVENT_FLAG,
496
Content[BSSID_WCID].Addr,
499
DBGPRINT_RAW(RT_DEBUG_ERROR, ("Rx MIC Value error\n"));
503
return (NDIS_STATUS_SUCCESS);
504
/*if ((pRxD->CipherAlg == CIPHER_AES) &&
505
(pHeader->Sequence == pAd->FragFrame.Sequence))
508
// Acceptable since the First FragFrame no CipherErr problem.
510
return(NDIS_STATUS_SUCCESS);
513
return (NDIS_STATUS_FAILURE);
516
return (NDIS_STATUS_SUCCESS);
519
BOOLEAN RTMPFreeTXDUponTxDmaDone(struct rt_rtmp_adapter *pAd, u8 QueIdx)
521
struct rt_rtmp_tx_ring *pTxRing;
522
struct rt_txd * pTxD;
525
struct rt_txd TxD, *pOriTxD;
526
/*unsigned long IrqFlags; */
527
BOOLEAN bReschedule = FALSE;
529
ASSERT(QueIdx < NUM_OF_TX_RING);
530
pTxRing = &pAd->TxRing[QueIdx];
532
RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF,
534
while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx) {
535
/* RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); */
537
/* static rate also need NICUpdateFifoStaCounters() function. */
538
/*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */
539
NICUpdateFifoStaCounters(pAd);
541
/* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
544
(struct rt_txd *) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
546
NdisMoveMemory(&TxD, pTxD, sizeof(struct rt_txd));
553
pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket;
555
PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1,
558
RELEASE_NDIS_PACKET(pAd, pPacket,
559
NDIS_STATUS_SUCCESS);
561
/*Always assign pNdisPacket as NULL after clear */
562
pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL;
565
pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket;
567
ASSERT(pPacket == NULL);
569
PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1,
572
RELEASE_NDIS_PACKET(pAd, pPacket,
573
NDIS_STATUS_SUCCESS);
575
/*Always assign pNextNdisPacket as NULL after clear */
576
pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket =
580
pAd->RalinkCounters.TransmittedByteCount +=
581
(pTxD->SDLen1 + pTxD->SDLen0);
582
pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx]++;
583
INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
584
/* get tx_tdx_idx again */
585
RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF,
587
NdisMoveMemory(pOriTxD, pTxD, sizeof(struct rt_txd));
589
/* RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); */
597
========================================================================
600
Process TX Rings DMA Done interrupt, running in DPC level
603
Adapter Pointer to our adapter
608
IRQL = DISPATCH_LEVEL
610
========================================================================
612
BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(struct rt_rtmp_adapter *pAd,
613
INT_SOURCE_CSR_STRUC TxRingBitmap)
616
unsigned long IrqFlags;
617
BOOLEAN bReschedule = FALSE;
619
/* Make sure Tx ring resource won't be used by other threads */
620
/*NdisAcquireSpinLock(&pAd->TxRingLock); */
622
RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
624
if (TxRingBitmap.field.Ac0DmaDone)
625
bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE);
627
if (TxRingBitmap.field.Ac3DmaDone)
628
bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO);
630
if (TxRingBitmap.field.Ac2DmaDone)
631
bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI);
633
if (TxRingBitmap.field.Ac1DmaDone)
634
bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK);
636
/* Make sure to release Tx ring resource */
637
/*NdisReleaseSpinLock(&pAd->TxRingLock); */
638
RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
640
/* Dequeue outgoing frames from TxSwQueue[] and process it */
641
RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
647
========================================================================
650
Process MGMT ring DMA done interrupt, running in DPC level
653
pAd Pointer to our adapter
658
IRQL = DISPATCH_LEVEL
662
========================================================================
664
void RTMPHandleMgmtRingDmaDoneInterrupt(struct rt_rtmp_adapter *pAd)
666
struct rt_txd * pTxD;
670
struct rt_rtmp_mgmt_ring *pMgmtRing = &pAd->MgmtRing;
672
NdisAcquireSpinLock(&pAd->MgmtRingLock);
674
RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx);
675
while (pMgmtRing->TxSwFreeIdx != pMgmtRing->TxDmaIdx) {
678
(struct rt_txd *) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].
681
pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket;
684
PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0,
686
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
688
pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL;
691
pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket;
693
PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1,
695
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
697
pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL;
698
INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE);
701
NdisReleaseSpinLock(&pAd->MgmtRingLock);
706
========================================================================
710
Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon.
712
IRQL = DISPATCH_LEVEL
714
========================================================================
716
void RTMPHandleTBTTInterrupt(struct rt_rtmp_adapter *pAd)
719
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) {
725
========================================================================
729
pAd Pointer to our adapter. Rewrite beacon content before next send-out.
731
IRQL = DISPATCH_LEVEL
733
========================================================================
735
void RTMPHandlePreTBTTInterrupt(struct rt_rtmp_adapter *pAd)
738
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) {
739
DBGPRINT(RT_DEBUG_TRACE,
740
("RTMPHandlePreTBTTInterrupt...\n"));
746
void RTMPHandleRxCoherentInterrupt(struct rt_rtmp_adapter *pAd)
748
WPDMA_GLO_CFG_STRUC GloCfg;
751
DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n"));
755
DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n"));
757
RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
759
GloCfg.field.EnTXWriteBackDDONE = 0;
760
GloCfg.field.EnableRxDMA = 0;
761
GloCfg.field.EnableTxDMA = 0;
762
RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
764
RTMPRingCleanUp(pAd, QID_AC_BE);
765
RTMPRingCleanUp(pAd, QID_AC_BK);
766
RTMPRingCleanUp(pAd, QID_AC_VI);
767
RTMPRingCleanUp(pAd, QID_AC_VO);
768
RTMPRingCleanUp(pAd, QID_MGMT);
769
RTMPRingCleanUp(pAd, QID_RX);
773
DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n"));
776
void *GetPacketFromRxRing(struct rt_rtmp_adapter *pAd,
777
OUT PRT28XX_RXD_STRUC pSaveRxD,
778
OUT BOOLEAN * pbReschedule,
781
struct rt_rxd * pRxD;
782
void *pRxPacket = NULL;
786
BOOLEAN bReschedule = FALSE;
787
struct rt_rtmp_dmacb *pRxCell;
789
RTMP_SEM_LOCK(&pAd->RxRingLock);
791
if (*pRxPending == 0) {
792
/* Get how may packets had been received */
793
RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx);
795
if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx) {
796
/* no more rx packets */
800
/* get rx pending count */
801
if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx)
803
pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx;
806
pAd->RxRing.RxDmaIdx + RX_RING_SIZE -
807
pAd->RxRing.RxSwReadIdx;
811
pRxCell = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx];
813
/* Point to Rx indexed rx ring descriptor */
814
pRxD = (struct rt_rxd *) pRxCell->AllocVa;
816
if (pRxD->DDONE == 0) {
818
/* DMAIndx had done but DDONE bit not ready */
823
/* return rx descriptor */
824
NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE);
827
RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE,
831
/* unmap the rx buffer */
832
PCI_UNMAP_SINGLE(pAd, pRxCell->DmaBuf.AllocPa,
833
pRxCell->DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
834
pRxPacket = pRxCell->pNdisPacket;
836
pRxCell->DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE;
837
pRxCell->pNdisPacket = (void *)pNewPacket;
838
pRxCell->DmaBuf.AllocVa = AllocVa;
839
pRxCell->DmaBuf.AllocPa = AllocPa;
840
/* update SDP0 to new buffer of rx packet */
841
pRxD->SDP0 = AllocPa;
843
/*DBGPRINT(RT_DEBUG_TRACE,("No Rx Buffer\n")); */
850
/* had handled one rx packet */
851
*pRxPending = *pRxPending - 1;
853
/* update rx descriptor and kick rx */
854
INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE);
856
pAd->RxRing.RxCpuIdx =
857
(pAd->RxRing.RxSwReadIdx ==
858
0) ? (RX_RING_SIZE - 1) : (pAd->RxRing.RxSwReadIdx - 1);
859
RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
862
RTMP_SEM_UNLOCK(&pAd->RxRingLock);
863
*pbReschedule = bReschedule;
867
int MlmeHardTransmitTxRing(struct rt_rtmp_adapter *pAd,
868
u8 QueIdx, void *pPacket)
870
struct rt_packet_info PacketInfo;
873
struct rt_txd * pTxD;
874
struct rt_header_802_11 * pHeader_802_11;
875
BOOLEAN bAckRequired, bInsertTimestamp;
876
unsigned long SrcBufPA;
879
unsigned long SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
880
struct rt_txwi * pFirstTxWI;
881
/*unsigned long i; */
882
/*HTTRANSMIT_SETTING MlmeTransmit; //Rate for this MGMT frame. */
883
unsigned long FreeNum;
884
struct rt_mac_table_entry *pMacEntry = NULL;
886
RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
888
if (pSrcBufVA == NULL) {
889
/* The buffer shouldn't be NULL */
890
return NDIS_STATUS_FAILURE;
892
/* Make sure MGMT ring resource won't be used by other threads */
893
/*NdisAcquireSpinLock(&pAd->TxRingLock); */
895
FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
898
/*NdisReleaseSpinLock(&pAd->TxRingLock); */
899
return NDIS_STATUS_FAILURE;
902
SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
904
pTxD = (struct rt_txd *) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
906
if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket) {
907
DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n"));
908
/*NdisReleaseSpinLock(&pAd->TxRingLock); */
909
return NDIS_STATUS_FAILURE;
913
/* outgoing frame always wakeup PHY to prevent frame lost */
914
/* if (pAd->StaCfg.Psm == PWR_SAVE) */
915
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
916
AsicForceWakeup(pAd, TRUE);
918
pFirstTxWI = (struct rt_txwi *) pSrcBufVA;
920
pHeader_802_11 = (struct rt_header_802_11 *) (pSrcBufVA + TXWI_SIZE);
921
if (pHeader_802_11->Addr1[0] & 0x01) {
922
MlmeRate = pAd->CommonCfg.BasicMlmeRate;
924
MlmeRate = pAd->CommonCfg.MlmeRate;
927
if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
928
(pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) {
929
pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
931
/* Verify Mlme rate for a / g bands. */
932
if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band */
936
/* Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE) */
937
/* Snice it's been set to 0 while on MgtMacHeaderInit */
938
/* By the way this will cause frame to be send on PWR_SAVE failed. */
941
/* In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame */
942
/* Data-Null packets also pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD */
943
if (pHeader_802_11->FC.Type != BTYPE_DATA) {
944
if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ)
945
|| !(pAd->CommonCfg.bAPSDCapable
946
&& pAd->CommonCfg.APEdcaParm.bAPSDCapable)) {
947
pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
949
pHeader_802_11->FC.PwrMgmt =
950
pAd->CommonCfg.bAPSDForcePowerSave;
954
bInsertTimestamp = FALSE;
955
if (pHeader_802_11->FC.Type == BTYPE_CNTL) /* must be PS-POLL */
957
bAckRequired = FALSE;
958
} else /* BTYPE_MGMT or BTYPE_DATA(must be NULL frame) */
960
if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST */
962
bAckRequired = FALSE;
963
pHeader_802_11->Duration = 0;
966
pHeader_802_11->Duration =
967
RTMPCalcDuration(pAd, MlmeRate, 14);
968
if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) {
969
bInsertTimestamp = TRUE;
973
pHeader_802_11->Sequence = pAd->Sequence++;
974
if (pAd->Sequence > 0xfff)
976
/* Before radar detection done, mgmt frame can not be sent but probe req */
977
/* Because we need to use probe req to trigger driver to send probe req in passive scan */
978
if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
979
&& (pAd->CommonCfg.bIEEE80211H == 1)
980
&& (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) {
981
DBGPRINT(RT_DEBUG_ERROR,
982
("MlmeHardTransmit --> radar detect not in normal mode!\n"));
983
/*NdisReleaseSpinLock(&pAd->TxRingLock); */
984
return (NDIS_STATUS_FAILURE);
987
/* fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET */
988
/* should always has only one ohysical buffer, and the whole frame size equals */
989
/* to the first scatter buffer size */
992
/* Initialize TX Descriptor */
993
/* For inter-frame gap, the number is for this frame and next frame */
994
/* For MLME rate, we will fix as 2Mb to match other vendor's implement */
995
/* pAd->CommonCfg.MlmeTransmit.field.MODE = 1; */
997
/* management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not. */
998
/* Only beacon use Nseq=TRUE. So here we use Nseq=FALSE. */
999
if (pMacEntry == NULL) {
1000
RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp,
1001
FALSE, bAckRequired, FALSE, 0, RESERVED_WCID,
1002
(SrcBufLen - TXWI_SIZE), PID_MGMT, 0,
1003
(u8)pAd->CommonCfg.MlmeTransmit.field.MCS,
1004
IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
1006
RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
1007
bInsertTimestamp, FALSE, bAckRequired, FALSE,
1008
0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE),
1009
pMacEntry->MaxHTPhyMode.field.MCS, 0,
1010
(u8)pMacEntry->MaxHTPhyMode.field.MCS,
1011
IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
1014
pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket;
1015
pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL;
1016
/* pFirstTxWI->MPDUtotalByteCount = SrcBufLen - TXWI_SIZE; */
1018
PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
1020
RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA);
1023
pTxD->SDLen0 = SrcBufLen;
1025
pTxD->SDPtr0 = SrcBufPA;
1028
pAd->RalinkCounters.KickTxCount++;
1029
pAd->RalinkCounters.OneSecTxDoneCount++;
1031
/* Increase TX_CTX_IDX, but write to register later. */
1032
INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
1034
RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * 0x10,
1035
pAd->TxRing[QueIdx].TxCpuIdx);
1037
/* Make sure to release MGMT ring resource */
1038
/* NdisReleaseSpinLock(&pAd->TxRingLock); */
1040
return NDIS_STATUS_SUCCESS;
1043
int MlmeDataHardTransmit(struct rt_rtmp_adapter *pAd,
1044
u8 QueIdx, void *pPacket)
1046
if ((pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
1048
return NDIS_STATUS_FAILURE;
1051
return MlmeHardTransmitTxRing(pAd, QueIdx, pPacket);
1055
========================================================================
1057
Routine Description:
1058
Calculates the duration which is required to transmit out frames
1059
with given size and specified rate.
1062
pTxD Pointer to transmit descriptor
1063
Ack Setting for Ack requirement bit
1064
Fragment Setting for Fragment bit
1065
RetryMode Setting for retry mode
1066
Ifs Setting for IFS gap
1067
Rate Setting for transmit rate
1068
Service Setting for service
1070
TxPreamble Short or Long preamble when using CCK rates
1071
QueIdx - 0-3, according to 802.11e/d4.4 June/2003
1076
IRQL = PASSIVE_LEVEL
1077
IRQL = DISPATCH_LEVEL
1079
========================================================================
1081
void RTMPWriteTxDescriptor(struct rt_rtmp_adapter *pAd,
1082
struct rt_txd * pTxD,
1083
IN BOOLEAN bWIV, u8 QueueSEL)
1086
/* Always use Long preamble before verifiation short preamble functionality works well. */
1087
/* Todo: remove the following line if short preamble functionality works */
1089
OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
1091
pTxD->WIV = (bWIV) ? 1 : 0;
1092
pTxD->QSEL = (QueueSEL);
1093
/*RT2860c?? fixed using EDCA queue for test... We doubt Queue1 has problem. 2006-09-26 Jan */
1094
/*pTxD->QSEL= FIFO_EDCA; */