/* ************************************************************************* * Ralink Tech Inc. * 5F., No.36, Taiyuan St., Jhubei City, * Hsinchu County 302, * Taiwan, R.O.C. * * (c) Copyright 2002-2007, Ralink Technology, Inc. * * 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. * * * ************************************************************************* Module Name: 2870_rtmp_init.c Abstract: Miniport generic portion header file Revision History: Who When What -------- ---------- ---------------------------------------------- Paul Lin 2002-08-01 created John Chang 2004-08-20 RT2561/2661 use scatter-gather scheme Jan Lee 2006-09-15 RT2860. Change for 802.11n , EEPROM, Led, BA, HT. Sample Lin 2007-05-31 Merge RT2860 and RT2870 drivers. */ #include "../rt_config.h" static void rx_done_tasklet(unsigned long data); static void rt2870_hcca_dma_done_tasklet(unsigned long data); static void rt2870_ac3_dma_done_tasklet(unsigned long data); static void rt2870_ac2_dma_done_tasklet(unsigned long data); static void rt2870_ac1_dma_done_tasklet(unsigned long data); static void rt2870_ac0_dma_done_tasklet(unsigned long data); static void rt2870_mgmt_dma_done_tasklet(unsigned long data); static void rt2870_null_frame_complete_tasklet(unsigned long data); static void rt2870_rts_frame_complete_tasklet(unsigned long data); static void rt2870_pspoll_frame_complete_tasklet(unsigned long data); static void rt2870_dataout_complete_tasklet(unsigned long data); /* ======================================================================== Routine Description: Initialize receive data structures. Arguments: pAd Pointer to our adapter Return Value: NDIS_STATUS_SUCCESS NDIS_STATUS_RESOURCES Note: Initialize all receive releated private buffer, include those define in RTMP_ADAPTER structure and all private data structures. The mahor work is to allocate buffer for each packet and chain buffer to NDIS packet descriptor. ======================================================================== */ NDIS_STATUS NICInitRecv( IN PRTMP_ADAPTER pAd) { UCHAR i; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitRecv\n")); pObj = pObj; //InterlockedExchange(&pAd->PendingRx, 0); pAd->PendingRx = 0; pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index pAd->NextRxBulkInIndex = 0 ; //RX_RING_SIZE -1; // Rx Bulk pointer pAd->NextRxBulkInPosition = 0; for (i = 0; i < (RX_RING_SIZE); i++) { PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); //Allocate URB pRxContext->pUrb = RTUSB_ALLOC_URB(0); if (pRxContext->pUrb == NULL) { Status = NDIS_STATUS_RESOURCES; goto out1; } // Allocate transfer buffer pRxContext->TransferBuffer = RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE, &pRxContext->data_dma); if (pRxContext->TransferBuffer == NULL) { Status = NDIS_STATUS_RESOURCES; goto out1; } NdisZeroMemory(pRxContext->TransferBuffer, MAX_RXBULK_SIZE); pRxContext->pAd = pAd; pRxContext->pIrp = NULL; pRxContext->InUse = FALSE; pRxContext->IRPPending = FALSE; pRxContext->Readable = FALSE; //pRxContext->ReorderInUse = FALSE; pRxContext->bRxHandling = FALSE; pRxContext->BulkInOffset = 0; } DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitRecv\n")); return Status; out1: for (i = 0; i < (RX_RING_SIZE); i++) { PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); if (NULL != pRxContext->TransferBuffer) { RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE, pRxContext->TransferBuffer, pRxContext->data_dma); pRxContext->TransferBuffer = NULL; } if (NULL != pRxContext->pUrb) { RTUSB_UNLINK_URB(pRxContext->pUrb); RTUSB_FREE_URB(pRxContext->pUrb); pRxContext->pUrb = NULL; } } return Status; } /* ======================================================================== Routine Description: Initialize transmit data structures. Arguments: pAd Pointer to our adapter Return Value: NDIS_STATUS_SUCCESS NDIS_STATUS_RESOURCES Note: ======================================================================== */ NDIS_STATUS NICInitTransmit( IN PRTMP_ADAPTER pAd) { #define LM_USB_ALLOC(pObj, Context, TB_Type, BufferSize, Status, msg1, err1, msg2, err2) \ Context->pUrb = RTUSB_ALLOC_URB(0); \ if (Context->pUrb == NULL) { \ DBGPRINT(RT_DEBUG_ERROR, msg1); \ Status = NDIS_STATUS_RESOURCES; \ goto err1; } \ \ Context->TransferBuffer = \ (TB_Type)RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, BufferSize, &Context->data_dma); \ if (Context->TransferBuffer == NULL) { \ DBGPRINT(RT_DEBUG_ERROR, msg2); \ Status = NDIS_STATUS_RESOURCES; \ goto err2; } #define LM_URB_FREE(pObj, Context, BufferSize) \ if (NULL != Context->pUrb) { \ RTUSB_UNLINK_URB(Context->pUrb); \ RTUSB_FREE_URB(Context->pUrb); \ Context->pUrb = NULL; } \ if (NULL != Context->TransferBuffer) { \ RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, BufferSize, \ Context->TransferBuffer, \ Context->data_dma); \ Context->TransferBuffer = NULL; } UCHAR i, acidx; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PTX_CONTEXT pNullContext = &(pAd->NullContext); PTX_CONTEXT pPsPollContext = &(pAd->PsPollContext); PTX_CONTEXT pRTSContext = &(pAd->RTSContext); PTX_CONTEXT pMLMEContext = NULL; // PHT_TX_CONTEXT pHTTXContext = NULL; POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; PVOID RingBaseVa; // RTMP_TX_RING *pTxRing; RTMP_MGMT_RING *pMgmtRing; DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTransmit\n")); pObj = pObj; // Init 4 set of Tx parameters for(acidx = 0; acidx < NUM_OF_TX_RING; acidx++) { // Initialize all Transmit releated queues InitializeQueueHeader(&pAd->TxSwQueue[acidx]); // Next Local tx ring pointer waiting for buck out pAd->NextBulkOutIndex[acidx] = acidx; pAd->BulkOutPending[acidx] = FALSE; // Buck Out control flag //pAd->DataBulkDoneIdx[acidx] = 0; } //pAd->NextMLMEIndex = 0; //pAd->PushMgmtIndex = 0; //pAd->PopMgmtIndex = 0; //InterlockedExchange(&pAd->MgmtQueueSize, 0); //InterlockedExchange(&pAd->TxCount, 0); //pAd->PrioRingFirstIndex = 0; //pAd->PrioRingTxCnt = 0; do { // // TX_RING_SIZE, 4 ACs // for(acidx=0; acidx<4; acidx++) { PHT_TX_CONTEXT pHTTXContext = &(pAd->TxContext[acidx]); NdisZeroMemory(pHTTXContext, sizeof(HT_TX_CONTEXT)); //Allocate URB LM_USB_ALLOC(pObj, pHTTXContext, PHTTX_BUFFER, sizeof(HTTX_BUFFER), Status, ("<-- ERROR in Alloc TX TxContext[%d] urb!! \n", acidx), done, ("<-- ERROR in Alloc TX TxContext[%d] HTTX_BUFFER !! \n", acidx), out1); NdisZeroMemory(pHTTXContext->TransferBuffer->Aggregation, 4); pHTTXContext->pAd = pAd; pHTTXContext->pIrp = NULL; pHTTXContext->IRPPending = FALSE; pHTTXContext->NextBulkOutPosition = 0; pHTTXContext->ENextBulkOutPosition = 0; pHTTXContext->CurWritePosition = 0; pHTTXContext->CurWriteRealPos = 0; pHTTXContext->BulkOutSize = 0; pHTTXContext->BulkOutPipeId = acidx; pHTTXContext->bRingEmpty = TRUE; pHTTXContext->bCopySavePad = FALSE; pAd->BulkOutPending[acidx] = FALSE; } // // MGMT_RING_SIZE // #if 0 for(i=0; iMLMEContext[i]); NdisZeroMemory(pMLMEContext, sizeof(TX_CONTEXT)); //Allocate URB LM_USB_ALLOC(pObj, pMLMEContext, PTX_BUFFER, sizeof(TX_BUFFER), Status, ("<-- ERROR in Alloc TX MLMEContext[%d] urb!! \n", i), out2, ("<-- ERROR in Alloc TX MLMEContext[%d] TX_BUFFER !! \n", i), out2); pMLMEContext->pAd = pAd; pMLMEContext->pIrp = NULL; pMLMEContext->InUse = FALSE; pMLMEContext->IRPPending = FALSE; } #else // Allocate MGMT ring descriptor's memory pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * sizeof(TX_CONTEXT); RTMPAllocateMemory(&pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize); if (pAd->MgmtDescRing.AllocVa == NULL) { DBGPRINT_ERR(("Failed to allocate a big buffer for MgmtDescRing!\n")); Status = NDIS_STATUS_RESOURCES; goto out1; } NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize); RingBaseVa = pAd->MgmtDescRing.AllocVa; // Initialize MGMT Ring and associated buffer memory pMgmtRing = &pAd->MgmtRing; for (i = 0; i < MGMT_RING_SIZE; i++) { // link the pre-allocated Mgmt buffer to MgmtRing.Cell pMgmtRing->Cell[i].AllocSize = sizeof(TX_CONTEXT); pMgmtRing->Cell[i].AllocVa = RingBaseVa; pMgmtRing->Cell[i].pNdisPacket = NULL; pMgmtRing->Cell[i].pNextNdisPacket = NULL; //Allocate URB for MLMEContext pMLMEContext = (PTX_CONTEXT) pAd->MgmtRing.Cell[i].AllocVa; pMLMEContext->pUrb = RTUSB_ALLOC_URB(0); if (pMLMEContext->pUrb == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("<-- ERROR in Alloc TX MLMEContext[%d] urb!! \n", i)); Status = NDIS_STATUS_RESOURCES; goto out2; } pMLMEContext->pAd = pAd; pMLMEContext->pIrp = NULL; pMLMEContext->TransferBuffer = NULL; pMLMEContext->InUse = FALSE; pMLMEContext->IRPPending = FALSE; pMLMEContext->bWaitingBulkOut = FALSE; pMLMEContext->BulkOutSize = 0; pMLMEContext->SelfIdx = i; // Offset to next ring descriptor address RingBaseVa = (PUCHAR) RingBaseVa + sizeof(TX_CONTEXT); } DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", i)); //pAd->MgmtRing.TxSwFreeIdx = (MGMT_RING_SIZE - 1); pAd->MgmtRing.TxSwFreeIdx = MGMT_RING_SIZE; pAd->MgmtRing.TxCpuIdx = 0; pAd->MgmtRing.TxDmaIdx = 0; #endif // // BEACON_RING_SIZE // for(i=0; iBeaconContext[i]); NdisZeroMemory(pBeaconContext, sizeof(TX_CONTEXT)); //Allocate URB LM_USB_ALLOC(pObj, pBeaconContext, PTX_BUFFER, sizeof(TX_BUFFER), Status, ("<-- ERROR in Alloc TX BeaconContext[%d] urb!! \n", i), out2, ("<-- ERROR in Alloc TX BeaconContext[%d] TX_BUFFER !! \n", i), out3); pBeaconContext->pAd = pAd; pBeaconContext->pIrp = NULL; pBeaconContext->InUse = FALSE; pBeaconContext->IRPPending = FALSE; } // // NullContext // NdisZeroMemory(pNullContext, sizeof(TX_CONTEXT)); //Allocate URB LM_USB_ALLOC(pObj, pNullContext, PTX_BUFFER, sizeof(TX_BUFFER), Status, ("<-- ERROR in Alloc TX NullContext urb!! \n"), out3, ("<-- ERROR in Alloc TX NullContext TX_BUFFER !! \n"), out4); pNullContext->pAd = pAd; pNullContext->pIrp = NULL; pNullContext->InUse = FALSE; pNullContext->IRPPending = FALSE; // // RTSContext // NdisZeroMemory(pRTSContext, sizeof(TX_CONTEXT)); //Allocate URB LM_USB_ALLOC(pObj, pRTSContext, PTX_BUFFER, sizeof(TX_BUFFER), Status, ("<-- ERROR in Alloc TX RTSContext urb!! \n"), out4, ("<-- ERROR in Alloc TX RTSContext TX_BUFFER !! \n"), out5); pRTSContext->pAd = pAd; pRTSContext->pIrp = NULL; pRTSContext->InUse = FALSE; pRTSContext->IRPPending = FALSE; // // PsPollContext // //NdisZeroMemory(pPsPollContext, sizeof(TX_CONTEXT)); //Allocate URB LM_USB_ALLOC(pObj, pPsPollContext, PTX_BUFFER, sizeof(TX_BUFFER), Status, ("<-- ERROR in Alloc TX PsPollContext urb!! \n"), out5, ("<-- ERROR in Alloc TX PsPollContext TX_BUFFER !! \n"), out6); pPsPollContext->pAd = pAd; pPsPollContext->pIrp = NULL; pPsPollContext->InUse = FALSE; pPsPollContext->IRPPending = FALSE; pPsPollContext->bAggregatible = FALSE; pPsPollContext->LastOne = TRUE; } while (FALSE); done: DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTransmit\n")); return Status; /* --------------------------- ERROR HANDLE --------------------------- */ out6: LM_URB_FREE(pObj, pPsPollContext, sizeof(TX_BUFFER)); out5: LM_URB_FREE(pObj, pRTSContext, sizeof(TX_BUFFER)); out4: LM_URB_FREE(pObj, pNullContext, sizeof(TX_BUFFER)); out3: for(i=0; iBeaconContext[i]); if (pBeaconContext) LM_URB_FREE(pObj, pBeaconContext, sizeof(TX_BUFFER)); } out2: if (pAd->MgmtDescRing.AllocVa) { pMgmtRing = &pAd->MgmtRing; for(i=0; iMgmtRing.Cell[i].AllocVa; if (pMLMEContext) LM_URB_FREE(pObj, pMLMEContext, sizeof(TX_BUFFER)); } NdisFreeMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize, 0); pAd->MgmtDescRing.AllocVa = NULL; } out1: for (acidx = 0; acidx < 4; acidx++) { PHT_TX_CONTEXT pTxContext = &(pAd->TxContext[acidx]); if (pTxContext) LM_URB_FREE(pObj, pTxContext, sizeof(HTTX_BUFFER)); } // Here we didn't have any pre-allocated memory need to free. return Status; } /* ======================================================================== Routine Description: Allocate DMA memory blocks for send, receive. Arguments: pAd Pointer to our adapter Return Value: NDIS_STATUS_SUCCESS NDIS_STATUS_FAILURE NDIS_STATUS_RESOURCES Note: ======================================================================== */ NDIS_STATUS RTMPAllocTxRxRingMemory( IN PRTMP_ADAPTER pAd) { // COUNTER_802_11 pCounter = &pAd->WlanCounters; NDIS_STATUS Status; INT num; DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); do { // Init the CmdQ and CmdQLock NdisAllocateSpinLock(&pAd->CmdQLock); NdisAcquireSpinLock(&pAd->CmdQLock); RTUSBInitializeCmdQ(&pAd->CmdQ); NdisReleaseSpinLock(&pAd->CmdQLock); NdisAllocateSpinLock(&pAd->MLMEBulkOutLock); //NdisAllocateSpinLock(&pAd->MLMEWaitQueueLock); NdisAllocateSpinLock(&pAd->BulkOutLock[0]); NdisAllocateSpinLock(&pAd->BulkOutLock[1]); NdisAllocateSpinLock(&pAd->BulkOutLock[2]); NdisAllocateSpinLock(&pAd->BulkOutLock[3]); NdisAllocateSpinLock(&pAd->BulkOutLock[4]); NdisAllocateSpinLock(&pAd->BulkOutLock[5]); NdisAllocateSpinLock(&pAd->BulkInLock); for (num = 0; num < NUM_OF_TX_RING; num++) { NdisAllocateSpinLock(&pAd->TxContextQueueLock[num]); } #ifdef RALINK_ATE NdisAllocateSpinLock(&pAd->GenericLock); #endif // RALINK_ATE // // NdisAllocateSpinLock(&pAd->MemLock); // Not used in RT28XX // NdisAllocateSpinLock(&pAd->MacTabLock); // init it in UserCfgInit() // NdisAllocateSpinLock(&pAd->BATabLock); // init it in BATableInit() // for(num=0; numBATable.BARecEntry[num].RxReRingLock); // } // // Init Mac Table // // MacTableInitialize(pAd); // // Init send data structures and related parameters // Status = NICInitTransmit(pAd); if (Status != NDIS_STATUS_SUCCESS) break; // // Init receive data structures and related parameters // Status = NICInitRecv(pAd); if (Status != NDIS_STATUS_SUCCESS) break; pAd->PendingIoCount = 1; } while (FALSE); NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME)); pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); if (pAd->FragFrame.pFragPacket == NULL) { Status = NDIS_STATUS_RESOURCES; } DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); return Status; } /* ======================================================================== Routine Description: Calls USB_InterfaceStop and frees memory allocated for the URBs calls NdisMDeregisterDevice and frees the memory allocated in VNetInitialize for the Adapter Object Arguments: *pAd the raxx interface data pointer Return Value: None Note: ======================================================================== */ VOID RTMPFreeTxRxRingMemory( IN PRTMP_ADAPTER pAd) { #define LM_URB_FREE(pObj, Context, BufferSize) \ if (NULL != Context->pUrb) { \ RTUSB_UNLINK_URB(Context->pUrb); \ RTUSB_FREE_URB(Context->pUrb); \ Context->pUrb = NULL; } \ if (NULL != Context->TransferBuffer) { \ RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, BufferSize, \ Context->TransferBuffer, \ Context->data_dma); \ Context->TransferBuffer = NULL; } UINT i, acidx; PTX_CONTEXT pNullContext = &pAd->NullContext; PTX_CONTEXT pPsPollContext = &pAd->PsPollContext; PTX_CONTEXT pRTSContext = &pAd->RTSContext; // PHT_TX_CONTEXT pHTTXContext; //PRTMP_REORDERBUF pReorderBuf; POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; // RTMP_TX_RING *pTxRing; DBGPRINT(RT_DEBUG_ERROR, ("---> RTMPFreeTxRxRingMemory\n")); pObj = pObj; // Free all resources for the RECEIVE buffer queue. for(i=0; i<(RX_RING_SIZE); i++) { PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); if (pRxContext) LM_URB_FREE(pObj, pRxContext, MAX_RXBULK_SIZE); } // Free PsPoll frame resource LM_URB_FREE(pObj, pPsPollContext, sizeof(TX_BUFFER)); // Free NULL frame resource LM_URB_FREE(pObj, pNullContext, sizeof(TX_BUFFER)); // Free RTS frame resource LM_URB_FREE(pObj, pRTSContext, sizeof(TX_BUFFER)); // Free beacon frame resource for(i=0; iBeaconContext[i]); if (pBeaconContext) LM_URB_FREE(pObj, pBeaconContext, sizeof(TX_BUFFER)); } // Free mgmt frame resource for(i = 0; i < MGMT_RING_SIZE; i++) { PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[i].AllocVa; //LM_URB_FREE(pObj, pMLMEContext, sizeof(TX_BUFFER)); if (NULL != pAd->MgmtRing.Cell[i].pNdisPacket) { RTMPFreeNdisPacket(pAd, pAd->MgmtRing.Cell[i].pNdisPacket); pAd->MgmtRing.Cell[i].pNdisPacket = NULL; pMLMEContext->TransferBuffer = NULL; } if (pMLMEContext) { if (NULL != pMLMEContext->pUrb) { RTUSB_UNLINK_URB(pMLMEContext->pUrb); RTUSB_FREE_URB(pMLMEContext->pUrb); pMLMEContext->pUrb = NULL; } } } if (pAd->MgmtDescRing.AllocVa) NdisFreeMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize, 0); // Free Tx frame resource for (acidx = 0; acidx < 4; acidx++) { PHT_TX_CONTEXT pHTTXContext = &(pAd->TxContext[acidx]); if (pHTTXContext) LM_URB_FREE(pObj, pHTTXContext, sizeof(HTTX_BUFFER)); } if (pAd->FragFrame.pFragPacket) RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS); for(i=0; i<6; i++) { NdisFreeSpinLock(&pAd->BulkOutLock[i]); } NdisFreeSpinLock(&pAd->BulkInLock); NdisFreeSpinLock(&pAd->MLMEBulkOutLock); NdisFreeSpinLock(&pAd->CmdQLock); #ifdef RALINK_ATE NdisFreeSpinLock(&pAd->GenericLock); #endif // RALINK_ATE // // Clear all pending bulk-out request flags. RTUSB_CLEAR_BULK_FLAG(pAd, 0xffffffff); // NdisFreeSpinLock(&pAd->MacTabLock); // for(i=0; iBATable.BARecEntry[i].RxReRingLock); // } DBGPRINT(RT_DEBUG_ERROR, ("<--- ReleaseAdapter\n")); } /* ======================================================================== Routine Description: Allocate memory for adapter control block. Arguments: pAd Pointer to our adapter Return Value: NDIS_STATUS_SUCCESS NDIS_STATUS_FAILURE NDIS_STATUS_RESOURCES Note: ======================================================================== */ NDIS_STATUS AdapterBlockAllocateMemory( IN PVOID handle, OUT PVOID *ppAd) { PUSB_DEV usb_dev; POS_COOKIE pObj = (POS_COOKIE) handle; usb_dev = pObj->pUsb_Dev; pObj->MLMEThr_task = NULL; pObj->RTUSBCmdThr_task = NULL; *ppAd = (PVOID)vmalloc(sizeof(RTMP_ADAPTER)); if (*ppAd) { NdisZeroMemory(*ppAd, sizeof(RTMP_ADAPTER)); ((PRTMP_ADAPTER)*ppAd)->OS_Cookie = handle; return (NDIS_STATUS_SUCCESS); } else { return (NDIS_STATUS_FAILURE); } } /* ======================================================================== Routine Description: Create kernel threads & tasklets. Arguments: *net_dev Pointer to wireless net device interface Return Value: NDIS_STATUS_SUCCESS NDIS_STATUS_FAILURE Note: ======================================================================== */ NDIS_STATUS CreateThreads( IN struct net_device *net_dev) { PRTMP_ADAPTER pAd = net_dev->ml_priv; POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; struct task_struct *tsk; //init_MUTEX(&(pAd->usbdev_semaphore)); init_MUTEX_LOCKED(&(pAd->mlme_semaphore)); init_completion (&pAd->mlmeComplete); init_MUTEX_LOCKED(&(pAd->RTUSBCmd_semaphore)); init_completion (&pAd->CmdQComplete); init_MUTEX_LOCKED(&(pAd->RTUSBTimer_semaphore)); init_completion (&pAd->TimerQComplete); // Creat MLME Thread pObj->MLMEThr_task = NULL; tsk = kthread_run(MlmeThread, pAd, pAd->net_dev->name); if (IS_ERR(tsk)) { printk (KERN_WARNING "%s: unable to start Mlme thread\n",pAd->net_dev->name); return NDIS_STATUS_FAILURE; } pObj->MLMEThr_task = tsk; // Wait for the thread to start wait_for_completion(&(pAd->mlmeComplete)); // Creat Command Thread pObj->RTUSBCmdThr_task = NULL; tsk = kthread_run(RTUSBCmdThread, pAd, pAd->net_dev->name); if (IS_ERR(tsk) < 0) { printk (KERN_WARNING "%s: unable to start RTUSBCmd thread\n",pAd->net_dev->name); return NDIS_STATUS_FAILURE; } pObj->RTUSBCmdThr_task = tsk; wait_for_completion(&(pAd->CmdQComplete)); pObj->TimerQThr_task = NULL; tsk = kthread_run(TimerQThread, pAd, pAd->net_dev->name); if (IS_ERR(tsk) < 0) { printk (KERN_WARNING "%s: unable to start TimerQThread\n",pAd->net_dev->name); return NDIS_STATUS_FAILURE; } pObj->TimerQThr_task = tsk; // Wait for the thread to start wait_for_completion(&(pAd->TimerQComplete)); // Create receive tasklet tasklet_init(&pObj->rx_done_task, rx_done_tasklet, (ULONG)pAd); tasklet_init(&pObj->mgmt_dma_done_task, rt2870_mgmt_dma_done_tasklet, (unsigned long)pAd); tasklet_init(&pObj->ac0_dma_done_task, rt2870_ac0_dma_done_tasklet, (unsigned long)pAd); tasklet_init(&pObj->ac1_dma_done_task, rt2870_ac1_dma_done_tasklet, (unsigned long)pAd); tasklet_init(&pObj->ac2_dma_done_task, rt2870_ac2_dma_done_tasklet, (unsigned long)pAd); tasklet_init(&pObj->ac3_dma_done_task, rt2870_ac3_dma_done_tasklet, (unsigned long)pAd); tasklet_init(&pObj->hcca_dma_done_task, rt2870_hcca_dma_done_tasklet, (unsigned long)pAd); tasklet_init(&pObj->tbtt_task, tbtt_tasklet, (unsigned long)pAd); tasklet_init(&pObj->null_frame_complete_task, rt2870_null_frame_complete_tasklet, (unsigned long)pAd); tasklet_init(&pObj->rts_frame_complete_task, rt2870_rts_frame_complete_tasklet, (unsigned long)pAd); tasklet_init(&pObj->pspoll_frame_complete_task, rt2870_pspoll_frame_complete_tasklet, (unsigned long)pAd); return NDIS_STATUS_SUCCESS; } #ifdef CONFIG_STA_SUPPORT /* ======================================================================== Routine Description: As STA's BSSID is a WC too, it uses shared key table. This function write correct unicast TX key to ASIC WCID. And we still make a copy in our MacTab.Content[BSSID_WCID].PairwiseKey. Caller guarantee TKIP/AES always has keyidx = 0. (pairwise key) Caller guarantee WEP calls this function when set Txkey, default key index=0~3. Arguments: pAd Pointer to our adapter pKey Pointer to the where the key stored Return Value: NDIS_SUCCESS Add key successfully Note: ======================================================================== */ VOID RTMPAddBSSIDCipher( IN PRTMP_ADAPTER pAd, IN UCHAR Aid, IN PNDIS_802_11_KEY pKey, IN UCHAR CipherAlg) { PUCHAR pTxMic, pRxMic; BOOLEAN bKeyRSC, bAuthenticator; // indicate the receive SC set by KeyRSC value // UCHAR CipherAlg; UCHAR i; ULONG WCIDAttri; USHORT offset; UCHAR KeyIdx, IVEIV[8]; UINT32 Value; DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddBSSIDCipher==> Aid = %d\n",Aid)); // Bit 29 of Add-key KeyRSC bKeyRSC = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE; // Bit 28 of Add-key Authenticator bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE; KeyIdx = (UCHAR)pKey->KeyIndex&0xff; if (KeyIdx > 4) return; if (pAd->MacTab.Content[Aid].PairwiseKey.CipherAlg == CIPHER_TKIP) { if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone) { // for WPA-None Tx, Rx MIC is the same pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 16; pRxMic = pTxMic; } else if (bAuthenticator == TRUE) { pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 16; pRxMic = (PUCHAR) (&pKey->KeyMaterial) + 24; } else { pRxMic = (PUCHAR) (&pKey->KeyMaterial) + 16; pTxMic = (PUCHAR) (&pKey->KeyMaterial) + 24; } offset = PAIRWISE_KEY_TABLE_BASE + (Aid * HW_KEY_ENTRY_SIZE) + 0x10; for (i=0; i<8; ) { Value = *(pTxMic+i); Value += (*(pTxMic+i+1)<<8); Value += (*(pTxMic+i+2)<<16); Value += (*(pTxMic+i+3)<<24); RTUSBWriteMACRegister(pAd, offset+i, Value); i+=4; } offset = PAIRWISE_KEY_TABLE_BASE + (Aid * HW_KEY_ENTRY_SIZE) + 0x18; for (i=0; i<8; ) { Value = *(pRxMic+i); Value += (*(pRxMic+i+1)<<8); Value += (*(pRxMic+i+2)<<16); Value += (*(pRxMic+i+3)<<24); RTUSBWriteMACRegister(pAd, offset+i, Value); i+=4; } // Only Key lenth equal to TKIP key have these NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.RxMic, pRxMic, 8); NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.TxMic, pTxMic, 8); DBGPRINT(RT_DEBUG_TRACE, (" TxMIC = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x \n", pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3], pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); DBGPRINT(RT_DEBUG_TRACE, (" RxMIC = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x \n", pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3], pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); } // 2. Record Security Key. pAd->MacTab.Content[BSSID_WCID].PairwiseKey.KeyLen= (UCHAR)pKey->KeyLength; NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength); // 3. Check RxTsc. And used to init to ASIC IV. if (bKeyRSC == TRUE) NdisMoveMemory(pAd->MacTab.Content[Aid].PairwiseKey.RxTsc, &pKey->KeyRSC, 6); else NdisZeroMemory(pAd->MacTab.Content[Aid].PairwiseKey.RxTsc, 6); // 4. Init TxTsc to one based on WiFi WPA specs pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[0] = 1; pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[1] = 0; pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[2] = 0; pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[3] = 0; pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[4] = 0; pAd->MacTab.Content[Aid].PairwiseKey.TxTsc[5] = 0; CipherAlg = pAd->MacTab.Content[Aid].PairwiseKey.CipherAlg; offset = PAIRWISE_KEY_TABLE_BASE + (Aid * HW_KEY_ENTRY_SIZE); RTUSBMultiWrite(pAd, (USHORT) offset, pKey->KeyMaterial, ((pKey->KeyLength == LEN_TKIP_KEY) ? 16 : (USHORT)pKey->KeyLength)); offset = SHARED_KEY_TABLE_BASE + (KeyIdx * HW_KEY_ENTRY_SIZE); RTUSBMultiWrite(pAd, (USHORT) offset, pKey->KeyMaterial, (USHORT)pKey->KeyLength); offset = PAIRWISE_IVEIV_TABLE_BASE + (Aid * HW_IVEIV_ENTRY_SIZE); NdisZeroMemory(IVEIV, 8); // IV/EIV if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) || (CipherAlg == CIPHER_AES)) { IVEIV[3] = 0x20; // Eiv bit on. keyid always 0 for pairwise key } // default key idx needs to set. // in TKIP/AES KeyIdx = 0 , WEP KeyIdx is default tx key. else { IVEIV[3] |= (KeyIdx<< 6); } RTUSBMultiWrite(pAd, (USHORT) offset, IVEIV, 8); // WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:1=PAIRWISE KEY, BSSIdx is 0 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) || (CipherAlg == CIPHER_AES)) { WCIDAttri = (CipherAlg<<1)|SHAREDKEYTABLE; } else WCIDAttri = (CipherAlg<<1)|SHAREDKEYTABLE; offset = MAC_WCID_ATTRIBUTE_BASE + (Aid* HW_WCID_ATTRI_SIZE); RTUSBWriteMACRegister(pAd, offset, WCIDAttri); RTUSBReadMACRegister(pAd, offset, &Value); DBGPRINT(RT_DEBUG_TRACE, ("BSSID_WCID : offset = %x, WCIDAttri = %lx\n", offset, WCIDAttri)); // pAddr // Add Bssid mac address at linkup. not here. check! /*offset = MAC_WCID_BASE + (BSSID_WCID * HW_WCID_ENTRY_SIZE); *for (i=0; iBSSID[i]); } */ DBGPRINT(RT_DEBUG_ERROR, ("AddBSSIDasWCIDEntry: Alg=%s, KeyLength = %d\n", CipherName[CipherAlg], pKey->KeyLength)); DBGPRINT(RT_DEBUG_TRACE, ("Key [idx=%x] [KeyLen = %d]\n", pKey->KeyIndex, pKey->KeyLength)); for(i=0; iKeyLength; i++) DBGPRINT_RAW(RT_DEBUG_TRACE,(" %x:", pKey->KeyMaterial[i])); DBGPRINT(RT_DEBUG_TRACE,(" \n")); } #endif // CONFIG_STA_SUPPORT // /* ======================================================================== Routine Description: Get a received packet. Arguments: pAd device control block pSaveRxD receive descriptor information *pbReschedule need reschedule flag *pRxPending pending received packet flag Return Value: the recieved packet Note: ======================================================================== */ #define RT2870_RXDMALEN_FIELD_SIZE 4 PNDIS_PACKET GetPacketFromRxRing( IN PRTMP_ADAPTER pAd, OUT PRT28XX_RXD_STRUC pSaveRxD, OUT BOOLEAN *pbReschedule, IN OUT UINT32 *pRxPending) { PRX_CONTEXT pRxContext; PNDIS_PACKET pSkb; PUCHAR pData; ULONG ThisFrameLen; ULONG RxBufferLength; PRXWI_STRUC pRxWI; pRxContext = &pAd->RxContext[pAd->NextRxBulkInReadIndex]; if ((pRxContext->Readable == FALSE) || (pRxContext->InUse == TRUE)) return NULL; RxBufferLength = pRxContext->BulkInOffset - pAd->ReadPosition; if (RxBufferLength < (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXWI_STRUC) + sizeof(RXINFO_STRUC))) { goto label_null; } pData = &pRxContext->TransferBuffer[pAd->ReadPosition]; /* 4KB */ // The RXDMA field is 4 bytes, now just use the first 2 bytes. The Length including the (RXWI + MSDU + Padding) ThisFrameLen = *pData + (*(pData+1)<<8); if (ThisFrameLen == 0) { DBGPRINT(RT_DEBUG_TRACE, ("BIRIdx(%d): RXDMALen is zero.[%ld], BulkInBufLen = %ld)\n", pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset)); goto label_null; } if ((ThisFrameLen&0x3) != 0) { DBGPRINT(RT_DEBUG_ERROR, ("BIRIdx(%d): RXDMALen not multiple of 4.[%ld], BulkInBufLen = %ld)\n", pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset)); goto label_null; } if ((ThisFrameLen + 8)> RxBufferLength) // 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXINFO_STRUC)) { DBGPRINT(RT_DEBUG_TRACE,("BIRIdx(%d):FrameLen(0x%lx) outranges. BulkInLen=0x%lx, remaining RxBufLen=0x%lx, ReadPos=0x%lx\n", pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset, RxBufferLength, pAd->ReadPosition)); // error frame. finish this loop goto label_null; } // skip USB frame length field pData += RT2870_RXDMALEN_FIELD_SIZE; pRxWI = (PRXWI_STRUC)pData; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pData, TYPE_RXWI); #endif // RT_BIG_ENDIAN // if (pRxWI->MPDUtotalByteCount > ThisFrameLen) { DBGPRINT(RT_DEBUG_ERROR, ("%s():pRxWIMPDUtotalByteCount(%d) large than RxDMALen(%ld)\n", __func__, pRxWI->MPDUtotalByteCount, ThisFrameLen)); goto label_null; } #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pData, TYPE_RXWI); #endif // RT_BIG_ENDIAN // // allocate a rx packet pSkb = dev_alloc_skb(ThisFrameLen); if (pSkb == NULL) { DBGPRINT(RT_DEBUG_ERROR,("%s():Cannot Allocate sk buffer for this Bulk-In buffer!\n", __func__)); goto label_null; } // copy the rx packet memcpy(skb_put(pSkb, ThisFrameLen), pData, ThisFrameLen); RTPKT_TO_OSPKT(pSkb)->dev = get_netdev_from_bssid(pAd, BSS0); RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pSkb), PKTSRC_NDIS); // copy RxD *pSaveRxD = *(PRXINFO_STRUC)(pData + ThisFrameLen); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pSaveRxD, TYPE_RXINFO); #endif // RT_BIG_ENDIAN // // update next packet read position. pAd->ReadPosition += (ThisFrameLen + RT2870_RXDMALEN_FIELD_SIZE + RXINFO_SIZE); // 8 for (RT2870_RXDMALEN_FIELD_SIZE + sizeof(RXINFO_STRUC)) return pSkb; label_null: return NULL; } /* ======================================================================== Routine Description: Handle received packets. Arguments: data - URB information pointer Return Value: None Note: ======================================================================== */ static void rx_done_tasklet(unsigned long data) { purbb_t pUrb; PRX_CONTEXT pRxContext; PRTMP_ADAPTER pAd; NTSTATUS Status; unsigned int IrqFlags; pUrb = (purbb_t)data; pRxContext = (PRX_CONTEXT)pUrb->context; pAd = pRxContext->pAd; Status = pUrb->status; RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext->InUse = FALSE; pRxContext->IRPPending = FALSE; pRxContext->BulkInOffset += pUrb->actual_length; //NdisInterlockedDecrement(&pAd->PendingRx); pAd->PendingRx--; if (Status == USB_ST_NOERROR) { pAd->BulkInComplete++; pAd->NextRxBulkInPosition = 0; if (pRxContext->BulkInOffset) // As jan's comment, it may bulk-in success but size is zero. { pRxContext->Readable = TRUE; INC_RING_INDEX(pAd->NextRxBulkInIndex, RX_RING_SIZE); } RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); } else // STATUS_OTHER { pAd->BulkInCompleteFail++; // Still read this packet although it may comtain wrong bytes. pRxContext->Readable = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); // Parsing all packets. because after reset, the index will reset to all zero. if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_BULKIN_RESET | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk In Failed. Status=%d, BIIdx=0x%x, BIRIdx=0x%x, actual_length= 0x%x\n", Status, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex, pRxContext->pUrb->actual_length)); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0); } } ASSERT((pRxContext->InUse == pRxContext->IRPPending)); #ifdef RALINK_ATE if (ATE_ON(pAd)) { // If the driver is in ATE mode and Rx frame is set into here. if (pAd->ContinBulkIn == TRUE) { RTUSBBulkReceive(pAd); } } else #endif // RALINK_ATE // RTUSBBulkReceive(pAd); return; } static void rt2870_mgmt_dma_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PTX_CONTEXT pMLMEContext; int index; PNDIS_PACKET pPacket; purbb_t pUrb; NTSTATUS Status; unsigned long IrqFlags; pUrb = (purbb_t)data; pMLMEContext = (PTX_CONTEXT)pUrb->context; pAd = pMLMEContext->pAd; Status = pUrb->status; index = pMLMEContext->SelfIdx; ASSERT((pAd->MgmtRing.TxDmaIdx == index)); RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); if (Status != USB_ST_NOERROR) { //Bulk-Out fail status handle if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out MLME Failed, Status=%d!\n", Status)); // TODO: How to handle about the MLMEBulkOut failed issue. Need to resend the mgmt pkt? RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); } } pAd->BulkOutPending[MGMTPIPEIDX] = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags); // Reset MLME context flags pMLMEContext->IRPPending = FALSE; pMLMEContext->InUse = FALSE; pMLMEContext->bWaitingBulkOut = FALSE; pMLMEContext->BulkOutSize = 0; pPacket = pAd->MgmtRing.Cell[index].pNdisPacket; pAd->MgmtRing.Cell[index].pNdisPacket = NULL; // Increase MgmtRing Index INC_RING_INDEX(pAd->MgmtRing.TxDmaIdx, MGMT_RING_SIZE); pAd->MgmtRing.TxSwFreeIdx++; RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags); // No-matter success or fail, we free the mgmt packet. if (pPacket) RTMPFreeNdisPacket(pAd, pPacket); if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { // do nothing and return directly. } else { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET) && ((pAd->bulkResetPipeid & BULKOUT_MGMT_RESET_FLAG) == BULKOUT_MGMT_RESET_FLAG)) { // For Mgmt Bulk-Out failed, ignore it now. RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { // Always call Bulk routine, even reset bulk. // The protectioon of rest bulk should be in BulkOut routine if (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE /* pMLMEContext->bWaitingBulkOut == TRUE */) { RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); } RTUSBKickBulkOut(pAd); } } } static void rt2870_hcca_dma_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId = 4; purbb_t pUrb; DBGPRINT_RAW(RT_DEBUG_ERROR, ("--->hcca_dma_done_tasklet\n")); pUrb = (purbb_t)data; pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; pAd = pHTTXContext->pAd; rt2870_dataout_complete_tasklet((unsigned long)pUrb); if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { // do nothing and return directly. } else { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) { RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && (pHTTXContext->bCurWriting == FALSE)) { RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); } RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL); RTUSBKickBulkOut(pAd); } } DBGPRINT_RAW(RT_DEBUG_ERROR, ("<---hcca_dma_done_tasklet\n")); return; } static void rt2870_ac3_dma_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId = 3; purbb_t pUrb; pUrb = (purbb_t)data; pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; pAd = pHTTXContext->pAd; rt2870_dataout_complete_tasklet((unsigned long)pUrb); if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { // do nothing and return directly. } else { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) { RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && (pHTTXContext->bCurWriting == FALSE)) { RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); } RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<3); RTUSBKickBulkOut(pAd); } } return; } static void rt2870_ac2_dma_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId = 2; purbb_t pUrb; pUrb = (purbb_t)data; pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; pAd = pHTTXContext->pAd; rt2870_dataout_complete_tasklet((unsigned long)pUrb); if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { // do nothing and return directly. } else { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) { RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && (pHTTXContext->bCurWriting == FALSE)) { RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); } RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<2); RTUSBKickBulkOut(pAd); } } return; } static void rt2870_ac1_dma_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId = 1; purbb_t pUrb; pUrb = (purbb_t)data; pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; pAd = pHTTXContext->pAd; rt2870_dataout_complete_tasklet((unsigned long)pUrb); if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { // do nothing and return directly. } else { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) { RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && (pHTTXContext->bCurWriting == FALSE)) { RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); } RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<1); RTUSBKickBulkOut(pAd); } } return; } static void rt2870_ac0_dma_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId = 0; purbb_t pUrb; pUrb = (purbb_t)data; pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; pAd = pHTTXContext->pAd; rt2870_dataout_complete_tasklet((unsigned long)pUrb); if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { // do nothing and return directly. } else { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) { RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && /* ((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && (pHTTXContext->bCurWriting == FALSE)) { RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); } RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL); RTUSBKickBulkOut(pAd); } } return; } static void rt2870_null_frame_complete_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PTX_CONTEXT pNullContext; purbb_t pUrb; NTSTATUS Status; unsigned long irqFlag; pUrb = (purbb_t)data; pNullContext = (PTX_CONTEXT)pUrb->context; pAd = pNullContext->pAd; Status = pUrb->status; // Reset Null frame context flags RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag); pNullContext->IRPPending = FALSE; pNullContext->InUse = FALSE; pAd->BulkOutPending[0] = FALSE; pAd->watchDogTxPendingCnt[0] = 0; if (Status == USB_ST_NOERROR) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); } else // STATUS_OTHER { if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out Null Frame Failed, ReasonCode=%d!\n", Status)); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); } } // Always call Bulk routine, even reset bulk. // The protectioon of rest bulk should be in BulkOut routine RTUSBKickBulkOut(pAd); } static void rt2870_rts_frame_complete_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PTX_CONTEXT pRTSContext; purbb_t pUrb; NTSTATUS Status; unsigned long irqFlag; pUrb = (purbb_t)data; pRTSContext = (PTX_CONTEXT)pUrb->context; pAd = pRTSContext->pAd; Status = pUrb->status; // Reset RTS frame context flags RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag); pRTSContext->IRPPending = FALSE; pRTSContext->InUse = FALSE; if (Status == USB_ST_NOERROR) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); } else // STATUS_OTHER { if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out RTS Frame Failed\n")); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); } } RTMP_SEM_LOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId]); pAd->BulkOutPending[pRTSContext->BulkOutPipeId] = FALSE; RTMP_SEM_UNLOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId]); // Always call Bulk routine, even reset bulk. // The protectioon of rest bulk should be in BulkOut routine RTUSBKickBulkOut(pAd); } static void rt2870_pspoll_frame_complete_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PTX_CONTEXT pPsPollContext; purbb_t pUrb; NTSTATUS Status; pUrb = (purbb_t)data; pPsPollContext = (PTX_CONTEXT)pUrb->context; pAd = pPsPollContext->pAd; Status = pUrb->status; // Reset PsPoll context flags pPsPollContext->IRPPending = FALSE; pPsPollContext->InUse = FALSE; pAd->watchDogTxPendingCnt[0] = 0; if (Status == USB_ST_NOERROR) { RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); } else // STATUS_OTHER { if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out PSPoll Failed\n")); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } } RTMP_SEM_LOCK(&pAd->BulkOutLock[0]); pAd->BulkOutPending[0] = FALSE; RTMP_SEM_UNLOCK(&pAd->BulkOutLock[0]); // Always call Bulk routine, even reset bulk. // The protectioon of rest bulk should be in BulkOut routine RTUSBKickBulkOut(pAd); } static void rt2870_dataout_complete_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; purbb_t pUrb; POS_COOKIE pObj; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId; NTSTATUS Status; unsigned long IrqFlags; pUrb = (purbb_t)data; pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; pAd = pHTTXContext->pAd; pObj = (POS_COOKIE) pAd->OS_Cookie; Status = pUrb->status; // Store BulkOut PipeId BulkOutPipeId = pHTTXContext->BulkOutPipeId; pAd->BulkOutDataOneSecCount++; //DBGPRINT(RT_DEBUG_LOUD, ("Done-B(%d):I=0x%lx, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", BulkOutPipeId, in_interrupt(), pHTTXContext->CurWritePosition, // pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); RTMP_IRQ_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->BulkOutPending[BulkOutPipeId] = FALSE; pHTTXContext->IRPPending = FALSE; pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0; if (Status == USB_ST_NOERROR) { pAd->BulkOutComplete++; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->Counters8023.GoodTransmits++; //RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); FREE_HTTX_RING(pAd, BulkOutPipeId, pHTTXContext); //RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); } else // STATUS_OTHER { PUCHAR pBuf; pAd->BulkOutCompleteOther++; pBuf = &pHTTXContext->TransferBuffer->field.WirelessPacket[pHTTXContext->NextBulkOutPosition]; if (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_BULKOUT_RESET))) { RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = BulkOutPipeId; pAd->bulkResetReq[BulkOutPipeId] = pAd->BulkOutReq; } RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkOutDataPacket failed: ReasonCode=%d!\n", Status)); DBGPRINT_RAW(RT_DEBUG_ERROR, ("\t>>BulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther)); DBGPRINT_RAW(RT_DEBUG_ERROR, ("\t>>BulkOut Header:%x %x %x %x %x %x %x %x\n", pBuf[0], pBuf[1], pBuf[2], pBuf[3], pBuf[4], pBuf[5], pBuf[6], pBuf[7])); //DBGPRINT_RAW(RT_DEBUG_ERROR, (">>BulkOutCompleteCancel=0x%x, BulkOutCompleteOther=0x%x\n", pAd->BulkOutCompleteCancel, pAd->BulkOutCompleteOther)); } // // bInUse = TRUE, means some process are filling TX data, after that must turn on bWaitingBulkOut // bWaitingBulkOut = TRUE, means the TX data are waiting for bulk out. // //RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); if ((pHTTXContext->ENextBulkOutPosition != pHTTXContext->CurWritePosition) && (pHTTXContext->ENextBulkOutPosition != (pHTTXContext->CurWritePosition+8)) && !RTUSB_TEST_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId))) { // Indicate There is data avaliable RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); } //RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); // Always call Bulk routine, even reset bulk. // The protection of rest bulk should be in BulkOut routine RTUSBKickBulkOut(pAd); } /* End of 2870_rtmp_init.c */