diff options
Diffstat (limited to 'drivers/staging/rt2860/common/cmm_mac_usb.c')
-rw-r--r-- | drivers/staging/rt2860/common/cmm_mac_usb.c | 1165 |
1 files changed, 1165 insertions, 0 deletions
diff --git a/drivers/staging/rt2860/common/cmm_mac_usb.c b/drivers/staging/rt2860/common/cmm_mac_usb.c new file mode 100644 index 00000000000..9dd6959cd5a --- /dev/null +++ b/drivers/staging/rt2860/common/cmm_mac_usb.c @@ -0,0 +1,1165 @@ +/* + ************************************************************************* + * 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. * + * * + ************************************************************************* +*/ + +#ifdef RTMP_MAC_USB + +#include "../rt_config.h" + +/* +======================================================================== +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 struct rt_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. +======================================================================== +*/ +int NICInitRecv(struct rt_rtmp_adapter *pAd) +{ + u8 i; + int Status = NDIS_STATUS_SUCCESS; + struct os_cookie *pObj = (struct os_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++) { + struct rt_rx_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(Status=%d)\n", Status)); + return Status; + +out1: + for (i = 0; i < (RX_RING_SIZE); i++) { + struct rt_rx_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: +======================================================================== +*/ +int NICInitTransmit(struct rt_rtmp_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; } + + u8 i, acidx; + int Status = NDIS_STATUS_SUCCESS; + struct rt_tx_context *pNullContext = &(pAd->NullContext); + struct rt_tx_context *pPsPollContext = &(pAd->PsPollContext); + struct rt_tx_context *pRTSContext = &(pAd->RTSContext); + struct rt_tx_context *pMLMEContext = NULL; +/* struct rt_ht_tx_context *pHTTXContext = NULL; */ + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; + void *RingBaseVa; +/* struct rt_rtmp_tx_ring *pTxRing; */ + struct rt_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++) { + struct rt_ht_tx_context *pHTTXContext = &(pAd->TxContext[acidx]); + + NdisZeroMemory(pHTTXContext, sizeof(struct rt_ht_tx_context)); + /*Allocate URB */ + LM_USB_ALLOC(pObj, pHTTXContext, struct rt_httx_buffer *, + sizeof(struct rt_httx_buffer), Status, + ("<-- ERROR in Alloc TX TxContext[%d] urb!\n", + acidx), done, + ("<-- ERROR in Alloc TX TxContext[%d] struct rt_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 */ + /* */ + + /* Allocate MGMT ring descriptor's memory */ + pAd->MgmtDescRing.AllocSize = + MGMT_RING_SIZE * sizeof(struct rt_tx_context); + os_alloc_mem(pAd, (u8 **) (&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(struct rt_tx_context); + pMgmtRing->Cell[i].AllocVa = RingBaseVa; + pMgmtRing->Cell[i].pNdisPacket = NULL; + pMgmtRing->Cell[i].pNextNdisPacket = NULL; + + /*Allocate URB for MLMEContext */ + pMLMEContext = + (struct rt_tx_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 = (u8 *)RingBaseVa + sizeof(struct rt_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; + + /* */ + /* BEACON_RING_SIZE */ + /* */ + for (i = 0; i < BEACON_RING_SIZE; i++) /* 2 */ + { + struct rt_tx_context *pBeaconContext = &(pAd->BeaconContext[i]); + + NdisZeroMemory(pBeaconContext, sizeof(struct rt_tx_context)); + + /*Allocate URB */ + LM_USB_ALLOC(pObj, pBeaconContext, struct rt_tx_buffer *, + sizeof(struct rt_tx_buffer), Status, + ("<-- ERROR in Alloc TX BeaconContext[%d] urb!\n", + i), out2, + ("<-- ERROR in Alloc TX BeaconContext[%d] struct rt_tx_buffer!\n", + i), out3); + + pBeaconContext->pAd = pAd; + pBeaconContext->pIrp = NULL; + pBeaconContext->InUse = FALSE; + pBeaconContext->IRPPending = FALSE; + } + + /* */ + /* NullContext */ + /* */ + NdisZeroMemory(pNullContext, sizeof(struct rt_tx_context)); + + /*Allocate URB */ + LM_USB_ALLOC(pObj, pNullContext, struct rt_tx_buffer *, sizeof(struct rt_tx_buffer), + Status, + ("<-- ERROR in Alloc TX NullContext urb!\n"), + out3, + ("<-- ERROR in Alloc TX NullContext struct rt_tx_buffer!\n"), + out4); + + pNullContext->pAd = pAd; + pNullContext->pIrp = NULL; + pNullContext->InUse = FALSE; + pNullContext->IRPPending = FALSE; + + /* */ + /* RTSContext */ + /* */ + NdisZeroMemory(pRTSContext, sizeof(struct rt_tx_context)); + + /*Allocate URB */ + LM_USB_ALLOC(pObj, pRTSContext, struct rt_tx_buffer *, sizeof(struct rt_tx_buffer), + Status, + ("<-- ERROR in Alloc TX RTSContext urb!\n"), + out4, + ("<-- ERROR in Alloc TX RTSContext struct rt_tx_buffer!\n"), + out5); + + pRTSContext->pAd = pAd; + pRTSContext->pIrp = NULL; + pRTSContext->InUse = FALSE; + pRTSContext->IRPPending = FALSE; + + /* */ + /* PsPollContext */ + /* */ + /*NdisZeroMemory(pPsPollContext, sizeof(struct rt_tx_context)); */ + /*Allocate URB */ + LM_USB_ALLOC(pObj, pPsPollContext, struct rt_tx_buffer *, + sizeof(struct rt_tx_buffer), Status, + ("<-- ERROR in Alloc TX PsPollContext urb!\n"), + out5, + ("<-- ERROR in Alloc TX PsPollContext struct rt_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(Status=%d)\n", Status)); + + return Status; + + /* --------------------------- ERROR HANDLE --------------------------- */ +out6: + LM_URB_FREE(pObj, pPsPollContext, sizeof(struct rt_tx_buffer)); + +out5: + LM_URB_FREE(pObj, pRTSContext, sizeof(struct rt_tx_buffer)); + +out4: + LM_URB_FREE(pObj, pNullContext, sizeof(struct rt_tx_buffer)); + +out3: + for (i = 0; i < BEACON_RING_SIZE; i++) { + struct rt_tx_context *pBeaconContext = &(pAd->BeaconContext[i]); + if (pBeaconContext) + LM_URB_FREE(pObj, pBeaconContext, sizeof(struct rt_tx_buffer)); + } + +out2: + if (pAd->MgmtDescRing.AllocVa) { + pMgmtRing = &pAd->MgmtRing; + for (i = 0; i < MGMT_RING_SIZE; i++) { + pMLMEContext = + (struct rt_tx_context *)pAd->MgmtRing.Cell[i].AllocVa; + if (pMLMEContext) + LM_URB_FREE(pObj, pMLMEContext, + sizeof(struct rt_tx_buffer)); + } + os_free_mem(pAd, pAd->MgmtDescRing.AllocVa); + pAd->MgmtDescRing.AllocVa = NULL; + } + +out1: + for (acidx = 0; acidx < 4; acidx++) { + struct rt_ht_tx_context *pTxContext = &(pAd->TxContext[acidx]); + if (pTxContext) + LM_URB_FREE(pObj, pTxContext, sizeof(struct rt_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: +======================================================================== +*/ +int RTMPAllocTxRxRingMemory(struct rt_rtmp_adapter *pAd) +{ +/* struct rt_counter_802_11 pCounter = &pAd->WlanCounters; */ + int Status; + int num; + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); + + do { + /* Init the struct rt_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]); + } + +/* NdisAllocateSpinLock(&pAd->MemLock); // Not used in RT28XX */ + +/* NdisAllocateSpinLock(&pAd->MacTabLock); // init it in UserCfgInit() */ +/* NdisAllocateSpinLock(&pAd->BATabLock); // init it in BATableInit() */ + +/* for(num=0; num<MAX_LEN_OF_BA_REC_TABLE; num++) */ +/* { */ +/* NdisAllocateSpinLock(&pAd->BATable.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(struct rt_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(struct rt_rtmp_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; } + + u32 i, acidx; + struct rt_tx_context *pNullContext = &pAd->NullContext; + struct rt_tx_context *pPsPollContext = &pAd->PsPollContext; + struct rt_tx_context *pRTSContext = &pAd->RTSContext; +/* struct rt_ht_tx_context *pHTTXContext; */ + /*PRTMP_REORDERBUF pReorderBuf; */ + struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie; +/* struct rt_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++) { + struct rt_rx_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(struct rt_tx_buffer)); + + /* Free NULL frame resource */ + LM_URB_FREE(pObj, pNullContext, sizeof(struct rt_tx_buffer)); + + /* Free RTS frame resource */ + LM_URB_FREE(pObj, pRTSContext, sizeof(struct rt_tx_buffer)); + + /* Free beacon frame resource */ + for (i = 0; i < BEACON_RING_SIZE; i++) { + struct rt_tx_context *pBeaconContext = &(pAd->BeaconContext[i]); + if (pBeaconContext) + LM_URB_FREE(pObj, pBeaconContext, sizeof(struct rt_tx_buffer)); + } + + /* Free mgmt frame resource */ + for (i = 0; i < MGMT_RING_SIZE; i++) { + struct rt_tx_context *pMLMEContext = + (struct rt_tx_context *)pAd->MgmtRing.Cell[i].AllocVa; + /*LM_URB_FREE(pObj, pMLMEContext, sizeof(struct rt_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) + os_free_mem(pAd, pAd->MgmtDescRing.AllocVa); + + /* Free Tx frame resource */ + for (acidx = 0; acidx < 4; acidx++) { + struct rt_ht_tx_context *pHTTXContext = &(pAd->TxContext[acidx]); + if (pHTTXContext) + LM_URB_FREE(pObj, pHTTXContext, sizeof(struct rt_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); + /* Clear all pending bulk-out request flags. */ + RTUSB_CLEAR_BULK_FLAG(pAd, 0xffffffff); + +/* NdisFreeSpinLock(&pAd->MacTabLock); */ + +/* for(i=0; i<MAX_LEN_OF_BA_REC_TABLE; i++) */ +/* { */ +/* NdisFreeSpinLock(&pAd->BATable.BARecEntry[i].RxReRingLock); */ +/* } */ + + DBGPRINT(RT_DEBUG_ERROR, ("<--- RTMPFreeTxRxRingMemory\n")); +} + +/* +======================================================================== +Routine Description: + Write WLAN MAC address to USB 2870. + +Arguments: + pAd Pointer to our adapter + +Return Value: + NDIS_STATUS_SUCCESS + +Note: +======================================================================== +*/ +int RTUSBWriteHWMACAddress(struct rt_rtmp_adapter *pAd) +{ + MAC_DW0_STRUC StaMacReg0; + MAC_DW1_STRUC StaMacReg1; + int Status = NDIS_STATUS_SUCCESS; + LARGE_INTEGER NOW; + + /* initialize the random number generator */ + RTMP_GetCurrentSystemTime(&NOW); + + if (pAd->bLocalAdminMAC != TRUE) { + pAd->CurrentAddress[0] = pAd->PermanentAddress[0]; + pAd->CurrentAddress[1] = pAd->PermanentAddress[1]; + pAd->CurrentAddress[2] = pAd->PermanentAddress[2]; + pAd->CurrentAddress[3] = pAd->PermanentAddress[3]; + pAd->CurrentAddress[4] = pAd->PermanentAddress[4]; + pAd->CurrentAddress[5] = pAd->PermanentAddress[5]; + } + /* Write New MAC address to MAC_CSR2 & MAC_CSR3 & let ASIC know our new MAC */ + StaMacReg0.field.Byte0 = pAd->CurrentAddress[0]; + StaMacReg0.field.Byte1 = pAd->CurrentAddress[1]; + StaMacReg0.field.Byte2 = pAd->CurrentAddress[2]; + StaMacReg0.field.Byte3 = pAd->CurrentAddress[3]; + StaMacReg1.field.Byte4 = pAd->CurrentAddress[4]; + StaMacReg1.field.Byte5 = pAd->CurrentAddress[5]; + StaMacReg1.field.U2MeMask = 0xff; + DBGPRINT_RAW(RT_DEBUG_TRACE, + ("Local MAC = %02x:%02x:%02x:%02x:%02x:%02x\n", + pAd->CurrentAddress[0], pAd->CurrentAddress[1], + pAd->CurrentAddress[2], pAd->CurrentAddress[3], + pAd->CurrentAddress[4], pAd->CurrentAddress[5])); + + RTUSBWriteMACRegister(pAd, MAC_ADDR_DW0, StaMacReg0.word); + RTUSBWriteMACRegister(pAd, MAC_ADDR_DW1, StaMacReg1.word); + return Status; +} + +/* +======================================================================== +Routine Description: + Disable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +void RT28XXDMADisable(struct rt_rtmp_adapter *pAd) +{ + /* no use */ +} + +/* +======================================================================== +Routine Description: + Enable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +void RT28XXDMAEnable(struct rt_rtmp_adapter *pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + USB_DMA_CFG_STRUC UsbCfg; + int i = 0; + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4); + do { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) + && (GloCfg.field.RxDMABusy == 0)) + break; + + DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n")); + RTMPusecDelay(1000); + i++; + } while (i < 200); + + RTMPusecDelay(50); + GloCfg.field.EnTXWriteBackDDONE = 1; + GloCfg.field.EnableRxDMA = 1; + GloCfg.field.EnableTxDMA = 1; + DBGPRINT(RT_DEBUG_TRACE, + ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word)); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); + + UsbCfg.word = 0; + UsbCfg.field.phyclear = 0; + /* usb version is 1.1,do not use bulk in aggregation */ + if (pAd->BulkInMaxPacketSize == 512) + UsbCfg.field.RxBulkAggEn = 1; + /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */ + UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE / 1024) - 3; + UsbCfg.field.RxBulkAggTOut = 0x80; /* 2006-10-18 */ + UsbCfg.field.RxBulkEn = 1; + UsbCfg.field.TxBulkEn = 1; + + RTUSBWriteMACRegister(pAd, USB_DMA_CFG, UsbCfg.word); + +} + +/******************************************************************** + * + * 2870 Beacon Update Related functions. + * + ********************************************************************/ + +/* +======================================================================== +Routine Description: + Write Beacon buffer to Asic. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +void RT28xx_UpdateBeaconToAsic(struct rt_rtmp_adapter *pAd, + int apidx, + unsigned long FrameLen, unsigned long UpdatePos) +{ + u8 *pBeaconFrame = NULL; + u8 *ptr; + u32 i, padding; + struct rt_beacon_sync *pBeaconSync = pAd->CommonCfg.pBeaconSync; + u32 longValue; +/* u16 shortValue; */ + BOOLEAN bBcnReq = FALSE; + u8 bcn_idx = 0; + + if (pBeaconFrame == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("pBeaconFrame is NULL!\n")); + return; + } + + if (pBeaconSync == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("pBeaconSync is NULL!\n")); + return; + } + /*if ((pAd->WdsTab.Mode == WDS_BRIDGE_MODE) || */ + /* ((pAd->ApCfg.MBSSID[apidx].MSSIDDev == NULL) || !(pAd->ApCfg.MBSSID[apidx].MSSIDDev->flags & IFF_UP)) */ + /* ) */ + if (bBcnReq == FALSE) { + /* when the ra interface is down, do not send its beacon frame */ + /* clear all zero */ + for (i = 0; i < TXWI_SIZE; i += 4) { + RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, + 0x00); + } + pBeaconSync->BeaconBitMap &= + (~(BEACON_BITMAP_MASK & (1 << bcn_idx))); + NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWI_SIZE); + } else { + ptr = (u8 *)& pAd->BeaconTxWI; + if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWI_SIZE) == FALSE) { /* If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames. */ + pBeaconSync->BeaconBitMap &= + (~(BEACON_BITMAP_MASK & (1 << bcn_idx))); + NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx], + &pAd->BeaconTxWI, TXWI_SIZE); + } + + if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) != + (1 << bcn_idx)) { + for (i = 0; i < TXWI_SIZE; i += 4) /* 16-byte TXWI field */ + { + longValue = + *ptr + (*(ptr + 1) << 8) + + (*(ptr + 2) << 16) + (*(ptr + 3) << 24); + RTMP_IO_WRITE32(pAd, + pAd->BeaconOffset[bcn_idx] + i, + longValue); + ptr += 4; + } + } + + ptr = pBeaconSync->BeaconBuf[bcn_idx]; + padding = (FrameLen & 0x01); + NdisZeroMemory((u8 *)(pBeaconFrame + FrameLen), padding); + FrameLen += padding; + for (i = 0; i < FrameLen /*HW_BEACON_OFFSET */ ; i += 2) { + if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE) { + NdisMoveMemory(ptr, pBeaconFrame, 2); + /*shortValue = *ptr + (*(ptr+1)<<8); */ + /*RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, shortValue); */ + RTUSBMultiWrite(pAd, + pAd->BeaconOffset[bcn_idx] + + TXWI_SIZE + i, ptr, 2); + } + ptr += 2; + pBeaconFrame += 2; + } + + pBeaconSync->BeaconBitMap |= (1 << bcn_idx); + + /* For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame. */ + } + +} + +void RTUSBBssBeaconStop(struct rt_rtmp_adapter *pAd) +{ + struct rt_beacon_sync *pBeaconSync; + int i, offset; + BOOLEAN Cancelled = TRUE; + + pBeaconSync = pAd->CommonCfg.pBeaconSync; + if (pBeaconSync && pBeaconSync->EnableBeacon) { + int NumOfBcn; + + { + NumOfBcn = MAX_MESH_NUM; + } + + RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled); + + for (i = 0; i < NumOfBcn; i++) { + NdisZeroMemory(pBeaconSync->BeaconBuf[i], + HW_BEACON_OFFSET); + NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); + + for (offset = 0; offset < HW_BEACON_OFFSET; offset += 4) + RTMP_IO_WRITE32(pAd, + pAd->BeaconOffset[i] + offset, + 0x00); + + pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; + pBeaconSync->TimIELocationInBeacon[i] = 0; + } + pBeaconSync->BeaconBitMap = 0; + pBeaconSync->DtimBitOn = 0; + } +} + +void RTUSBBssBeaconStart(struct rt_rtmp_adapter *pAd) +{ + int apidx; + struct rt_beacon_sync *pBeaconSync; +/* LARGE_INTEGER tsfTime, deltaTime; */ + + pBeaconSync = pAd->CommonCfg.pBeaconSync; + if (pBeaconSync && pBeaconSync->EnableBeacon) { + int NumOfBcn; + + { + NumOfBcn = MAX_MESH_NUM; + } + + for (apidx = 0; apidx < NumOfBcn; apidx++) { + u8 CapabilityInfoLocationInBeacon = 0; + u8 TimIELocationInBeacon = 0; + + NdisZeroMemory(pBeaconSync->BeaconBuf[apidx], + HW_BEACON_OFFSET); + pBeaconSync->CapabilityInfoLocationInBeacon[apidx] = + CapabilityInfoLocationInBeacon; + pBeaconSync->TimIELocationInBeacon[apidx] = + TimIELocationInBeacon; + NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx], + TXWI_SIZE); + } + pBeaconSync->BeaconBitMap = 0; + pBeaconSync->DtimBitOn = 0; + pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE; + + pAd->CommonCfg.BeaconAdjust = 0; + pAd->CommonCfg.BeaconFactor = + 0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10); + pAd->CommonCfg.BeaconRemain = + (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1; + DBGPRINT(RT_DEBUG_TRACE, + ("RTUSBBssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n", + pAd->CommonCfg.BeaconFactor, + pAd->CommonCfg.BeaconRemain)); + RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer, + 10 /*pAd->CommonCfg.BeaconPeriod */ ); + + } +} + +void RTUSBBssBeaconInit(struct rt_rtmp_adapter *pAd) +{ + struct rt_beacon_sync *pBeaconSync; + int i; + + os_alloc_mem(pAd, (u8 **) (&pAd->CommonCfg.pBeaconSync), + sizeof(struct rt_beacon_sync)); + /*NdisAllocMemory(pAd->CommonCfg.pBeaconSync, sizeof(struct rt_beacon_sync), MEM_ALLOC_FLAG); */ + if (pAd->CommonCfg.pBeaconSync) { + pBeaconSync = pAd->CommonCfg.pBeaconSync; + NdisZeroMemory(pBeaconSync, sizeof(struct rt_beacon_sync)); + for (i = 0; i < HW_BEACON_MAX_COUNT; i++) { + NdisZeroMemory(pBeaconSync->BeaconBuf[i], + HW_BEACON_OFFSET); + pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; + pBeaconSync->TimIELocationInBeacon[i] = 0; + NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); + } + pBeaconSync->BeaconBitMap = 0; + + /*RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE); */ + pBeaconSync->EnableBeacon = TRUE; + } +} + +void RTUSBBssBeaconExit(struct rt_rtmp_adapter *pAd) +{ + struct rt_beacon_sync *pBeaconSync; + BOOLEAN Cancelled = TRUE; + int i; + + if (pAd->CommonCfg.pBeaconSync) { + pBeaconSync = pAd->CommonCfg.pBeaconSync; + pBeaconSync->EnableBeacon = FALSE; + RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled); + pBeaconSync->BeaconBitMap = 0; + + for (i = 0; i < HW_BEACON_MAX_COUNT; i++) { + NdisZeroMemory(pBeaconSync->BeaconBuf[i], + HW_BEACON_OFFSET); + pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0; + pBeaconSync->TimIELocationInBeacon[i] = 0; + NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWI_SIZE); + } + + os_free_mem(pAd, pAd->CommonCfg.pBeaconSync); + pAd->CommonCfg.pBeaconSync = NULL; + } +} + +/* + ======================================================================== + Routine Description: + For device work as AP mode but didn't have TBTT interrupt event, we need a mechanism + to update the beacon context in each Beacon interval. Here we use a periodical timer + to simulate the TBTT interrupt to handle the beacon context update. + + Arguments: + SystemSpecific1 - Not used. + FunctionContext - Pointer to our Adapter context. + SystemSpecific2 - Not used. + SystemSpecific3 - Not used. + + Return Value: + None + + ======================================================================== +*/ +void BeaconUpdateExec(void *SystemSpecific1, + void *FunctionContext, + void *SystemSpecific2, void *SystemSpecific3) +{ + struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext; + LARGE_INTEGER tsfTime_a; /*, tsfTime_b, deltaTime_exp, deltaTime_ab; */ + u32 delta, delta2MS, period2US, remain, remain_low, remain_high; +/* BOOLEAN positive; */ + + if (pAd->CommonCfg.IsUpdateBeacon == TRUE) { + ReSyncBeaconTime(pAd); + + } + + RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart); + RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart); + + /*positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp); */ + period2US = (pAd->CommonCfg.BeaconPeriod << 10); + remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart; + remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10); + remain = + (remain_high + remain_low) % (pAd->CommonCfg.BeaconPeriod << 10); + delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain; + + delta2MS = (delta >> 10); + if (delta2MS > 150) { + pAd->CommonCfg.BeaconUpdateTimer.TimerValue = 100; + pAd->CommonCfg.IsUpdateBeacon = FALSE; + } else { + pAd->CommonCfg.BeaconUpdateTimer.TimerValue = delta2MS + 10; + pAd->CommonCfg.IsUpdateBeacon = TRUE; + } + +} + +/******************************************************************** + * + * 2870 Radio on/off Related functions. + * + ********************************************************************/ +void RT28xxUsbMlmeRadioOn(struct rt_rtmp_adapter *pAd) +{ + struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps; + + DBGPRINT(RT_DEBUG_TRACE, ("RT28xxUsbMlmeRadioOn()\n")); + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + { + AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02); + RTMPusecDelay(10000); + } + /*NICResetFromError(pAd); */ + + /* Enable Tx/Rx */ + RTMPEnableRxTx(pAd); + + if (pChipOps->AsicReverseRfFromSleepMode) + pChipOps->AsicReverseRfFromSleepMode(pAd); + + /* Clear Radio off flag */ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + + RTUSBBulkReceive(pAd); + + /* Set LED */ + RTMPSetLED(pAd, LED_RADIO_ON); +} + +void RT28xxUsbMlmeRadioOFF(struct rt_rtmp_adapter *pAd) +{ + WPDMA_GLO_CFG_STRUC GloCfg; + u32 Value, i; + + DBGPRINT(RT_DEBUG_TRACE, ("RT28xxUsbMlmeRadioOFF()\n")); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + /* Clear PMKID cache. */ + pAd->StaCfg.SavedPMKNum = 0; + RTMPZeroMemory(pAd->StaCfg.SavedPMK, (PMKID_NO * sizeof(struct rt_bssid_info))); + + /* Link down first if any association exists */ + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) { + struct rt_mlme_disassoc_req DisReq; + struct rt_mlme_queue_elem *pMsgElem = + (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem), + MEM_ALLOC_FLAG); + + if (pMsgElem) { + COPY_MAC_ADDR(&DisReq.Addr, + pAd->CommonCfg.Bssid); + DisReq.Reason = REASON_DISASSOC_STA_LEAVING; + + pMsgElem->Machine = ASSOC_STATE_MACHINE; + pMsgElem->MsgType = MT2_MLME_DISASSOC_REQ; + pMsgElem->MsgLen = + sizeof(struct rt_mlme_disassoc_req); + NdisMoveMemory(pMsgElem->Msg, &DisReq, + sizeof + (struct rt_mlme_disassoc_req)); + + MlmeDisassocReqAction(pAd, pMsgElem); + kfree(pMsgElem); + + RTMPusecDelay(1000); + } + } + } + /* Set Radio off flag */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + + { + /* Link down first if any association exists */ + if (INFRA_ON(pAd) || ADHOC_ON(pAd)) + LinkDown(pAd, FALSE); + RTMPusecDelay(10000); + + /*========================================== */ + /* Clean up old bss table */ + BssTableInit(&pAd->ScanTab); + } + + /* Set LED */ + RTMPSetLED(pAd, LED_RADIO_OFF); + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) { + /* Must using 40MHz. */ + AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel); + } else { + /* Must using 20MHz. */ + AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); + } + + /* Disable Tx/Rx DMA */ + RTUSBReadMACRegister(pAd, WPDMA_GLO_CFG, &GloCfg.word); /* disable DMA */ + GloCfg.field.EnableTxDMA = 0; + GloCfg.field.EnableRxDMA = 0; + RTUSBWriteMACRegister(pAd, WPDMA_GLO_CFG, GloCfg.word); /* abort all TX rings */ + + /* Waiting for DMA idle */ + i = 0; + do { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) + && (GloCfg.field.RxDMABusy == 0)) + break; + + RTMPusecDelay(1000); + } while (i++ < 100); + + /* Disable MAC Tx/Rx */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value &= (0xfffffff3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); + + { + AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02); + } +} + +#endif /* RTMP_MAC_USB // */ |