📄 rtusb_io.c
字号:
========================================================================*/VOID RTUSBDequeueCmd( IN PCmdQ cmdq, OUT PCmdQElmt *pcmdqelmt){ *pcmdqelmt = cmdq->head; if (*pcmdqelmt != NULL) { cmdq->head = cmdq->head->next; cmdq->size--; if (cmdq->size == 0) cmdq->tail = NULL; }}/* ======================================================================== usb_control_msg - Builds a control urb, sends it off and waits for completion @dev: pointer to the usb device to send the message to @pipe: endpoint "pipe" to send the message to @request: USB message request value @requesttype: USB message request type value @value: USB message value @index: USB message index value @data: pointer to the data to send @size: length in bytes of the data to send @timeout: time in jiffies to wait for the message to complete before timing out (if 0 the wait is forever) Context: !in_interrupt () This function sends a simple control message to a specified endpoint and waits for the message to complete, or timeout. If successful, it returns the number of bytes transferred, otherwise a negative error number. Don't use this function from within an interrupt context, like a bottom half handler. If you need an asynchronous message, or need to send a message from within interrupt context, use usb_submit_urb() If a thread in your driver uses this call, make sure your disconnect() method can wait for it to complete. Since you don't have a handle on the URB used, you can't cancel the request. Routine Description: Arguments: Return Value: Note: ========================================================================*/NTSTATUS RTUSB_VendorRequest( IN PRTMP_ADAPTER pAd, IN UINT32 TransferFlags, IN UCHAR RequestType, IN UCHAR Request, IN USHORT Value, IN USHORT Index, IN PVOID TransferBuffer, IN UINT32 TransferBufferLength){ int ret = 0; POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { DBGPRINT(RT_DEBUG_ERROR, ("device disconnected\n")); return -1; } else if (in_interrupt()) { DBGPRINT(RT_DEBUG_ERROR, ("in_interrupt, RTUSB_VendorRequest Request%02x Value%04x Offset%04x\n",Request,Value,Index)); return -1; } else {#define MAX_RETRY_COUNT 10 int retryCount = 0; void *tmpBuf = TransferBuffer; // Acquire Control token#ifdef INF_AMAZON_SE //Semaphore fix INF_AMAZON_SE hang //pAd->UsbVendorReqBuf is the swap for DEVICE_VENDOR_REQUEST_IN to fix dma bug. ret = down_interruptible(&(pAd->UsbVendorReq_semaphore)); if (pAd->UsbVendorReqBuf) { ASSERT(TransferBufferLength <MAX_PARAM_BUFFER_SIZE); tmpBuf = (void *)pAd->UsbVendorReqBuf; NdisZeroMemory(pAd->UsbVendorReqBuf, TransferBufferLength); if (RequestType == DEVICE_VENDOR_REQUEST_OUT) NdisMoveMemory(tmpBuf, TransferBuffer, TransferBufferLength); }#endif // INF_AMAZON_SE //#ifdef ST //Semaphore fix ST hang //pAd->UsbVendorReqBuf is the swap for DEVICE_VENDOR_REQUEST_IN to fix dma bug. ret = down_interruptible(&(pAd->UsbVendorReq_semaphore)); if (pAd->UsbVendorReqBuf) { ASSERT(TransferBufferLength <MAX_PARAM_BUFFER_SIZE); tmpBuf = (void *)pAd->UsbVendorReqBuf; NdisZeroMemory(pAd->UsbVendorReqBuf, TransferBufferLength); if( RequestType == DEVICE_VENDOR_REQUEST_OUT) NdisMoveMemory(tmpBuf, TransferBuffer, TransferBufferLength); }#endif // ST // do { if( RequestType == DEVICE_VENDOR_REQUEST_OUT) ret=usb_control_msg(pObj->pUsb_Dev, usb_sndctrlpipe( pObj->pUsb_Dev, 0 ), Request, RequestType, Value,Index, tmpBuf, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES); else if(RequestType == DEVICE_VENDOR_REQUEST_IN) ret=usb_control_msg(pObj->pUsb_Dev, usb_rcvctrlpipe( pObj->pUsb_Dev, 0 ), Request, RequestType, Value,Index, tmpBuf, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES); else { DBGPRINT(RT_DEBUG_ERROR, ("vendor request direction is failed\n")); ret = -1; } retryCount++; if (ret < 0) { DBGPRINT(RT_DEBUG_OFF, ("#\n")); RTMPusecDelay(5000); } } while((ret < 0) && (retryCount < MAX_RETRY_COUNT)); #ifdef INF_AMAZON_SE if ((pAd->UsbVendorReqBuf) && (RequestType == DEVICE_VENDOR_REQUEST_IN)) NdisMoveMemory(TransferBuffer, tmpBuf, TransferBufferLength); up(&(pAd->UsbVendorReq_semaphore));#endif // INF_AMAZON_SE //#ifdef ST if ((pAd->UsbVendorReqBuf) && (RequestType == DEVICE_VENDOR_REQUEST_IN)) NdisMoveMemory(TransferBuffer, tmpBuf, TransferBufferLength); up(&(pAd->UsbVendorReq_semaphore));#endif // ST // if (ret < 0) {// DBGPRINT(RT_DEBUG_ERROR, ("USBVendorRequest failed ret=%d \n",ret)); DBGPRINT(RT_DEBUG_ERROR, ("RTUSB_VendorRequest failed(%d),TxFlags=0x%x, ReqType=%s, Req=0x%x, Index=0x%x\n", ret, TransferFlags, (RequestType == DEVICE_VENDOR_REQUEST_OUT ? "OUT" : "IN"), Request, Index)); if (Request == 0x2) DBGPRINT(RT_DEBUG_ERROR, ("\tRequest Value=0x%04x!\n", Value)); if ((TransferBuffer!= NULL) && (TransferBufferLength > 0)) hex_dump("Failed TransferBuffer value", TransferBuffer, TransferBufferLength); } } if (ret != -1) return STATUS_SUCCESS; else return STATUS_UNSUCCESSFUL;}/* ======================================================================== Routine Description: Creates an IRP to submite an IOCTL_INTERNAL_USB_RESET_PORT synchronously. Callers of this function must be running at PASSIVE LEVEL. Arguments: Return Value: Note: ========================================================================*/NTSTATUS RTUSB_ResetDevice( IN PRTMP_ADAPTER pAd){ NTSTATUS Status = TRUE; DBGPRINT_RAW(RT_DEBUG_TRACE, ("--->USB_ResetDevice\n")); //RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS); return Status;} VOID CMDHandler( IN PRTMP_ADAPTER pAd) { PCmdQElmt cmdqelmt; PUCHAR pData; NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; // ULONG Now = 0; NTSTATUS ntStatus;// unsigned long IrqFlags; while (pAd && pAd->CmdQ.size > 0) { NdisStatus = NDIS_STATUS_SUCCESS; NdisAcquireSpinLock(&pAd->CmdQLock); RTUSBDequeueCmd(&pAd->CmdQ, &cmdqelmt); NdisReleaseSpinLock(&pAd->CmdQLock); if (cmdqelmt == NULL) break; pData = cmdqelmt->buffer; if(!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { switch (cmdqelmt->command) { case CMDTHREAD_CHECK_GPIO: {#ifdef CONFIG_STA_SUPPORT UINT32 data;#endif // CONFIG_STA_SUPPORT //#ifdef RALINK_ATE if(ATE_ON(pAd)) { ATEDBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); break; } #endif // RALINK_ATE //#ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { // Read GPIO pin2 as Hardware controlled radio state RTUSBReadMACRegister( pAd, GPIO_CTRL_CFG, &data); if (data & 0x04) { pAd->StaCfg.bHwRadio = TRUE; } else { pAd->StaCfg.bHwRadio = FALSE; } if(pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) { pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); if(pAd->StaCfg.bRadio == TRUE) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("!!! Radio On !!!\n")); MlmeRadioOn(pAd); // Update extra information pAd->ExtraInfo = EXTRA_INFO_CLEAR; } else { DBGPRINT_RAW(RT_DEBUG_ERROR, ("!!! Radio Off !!!\n")); MlmeRadioOff(pAd); // Update extra information pAd->ExtraInfo = HW_RADIO_OFF; } } }#endif // CONFIG_STA_SUPPORT // } break; #ifdef CONFIG_STA_SUPPORT case CMDTHREAD_QKERIODIC_EXECUT: { StaQuickResponeForRateUpExec(NULL, pAd, NULL, NULL); } break;#endif // CONFIG_STA_SUPPORT // case CMDTHREAD_RESET_BULK_OUT: { UINT32 MACValue; UCHAR Index; int ret=0; PHT_TX_CONTEXT pHTTXContext;// RTMP_TX_RING *pTxRing; unsigned long IrqFlags; DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_OUT(ResetPipeid=0x%0x)===>\n", pAd->bulkResetPipeid)); // All transfers must be aborted or cancelled before attempting to reset the pipe. //RTUSBCancelPendingBulkOutIRP(pAd); // Wait 10ms to let previous packet that are already in HW FIFO to clear. by MAXLEE 12-25-2007 Index = 0; do { RTUSBReadMACRegister(pAd, TXRXQ_PCNT, &MACValue); if ((MACValue & 0xf00000/*0x800000*/) == 0) break; Index++; RTMPusecDelay(10000); }while(Index < 100); MACValue = 0; RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); // To prevent Read Register error, we 2nd check the validity. if ((MACValue & 0xc00000) == 0) RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); // To prevent Read Register error, we 3rd check the validity. if ((MACValue & 0xc00000) == 0) RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); MACValue |= 0x80000; RTUSBWriteMACRegister(pAd, USB_DMA_CFG, MACValue); // Wait 1ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007 RTMPusecDelay(1000); MACValue &= (~0x80000); RTUSBWriteMACRegister(pAd, USB_DMA_CFG, MACValue); DBGPRINT_RAW(RT_DEBUG_TRACE, ("\tSet 0x2a0 bit19. Clear USB DMA TX path\n")); // Wait 5ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007 //RTMPusecDelay(5000); if ((pAd->bulkResetPipeid & BULKOUT_MGMT_RESET_FLAG) == BULKOUT_MGMT_RESET_FLAG) { RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); if (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE /* pMLMEContext->bWaitingBulkOut == TRUE */) { RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); } RTUSBKickBulkOut(pAd); DBGPRINT_RAW(RT_DEBUG_TRACE, ("\tTX MGMT RECOVER Done!\n")); } else { pHTTXContext = &(pAd->TxContext[pAd->bulkResetPipeid]); //NdisAcquireSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); if ( pAd->BulkOutPending[pAd->bulkResetPipeid] == FALSE) { pAd->BulkOutPending[pAd->bulkResetPipeid] = TRUE; pHTTXContext->IRPPending = TRUE; pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 1; // no matter what, clean the flag RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); //NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);#ifdef RALINK_ATE if(ATE_ON(pAd)) { ret = ATEResetBulkOut(pAd); } else#endif // RALINK_ATE // { RTUSBInitHTTxDesc(pAd, pHTTXContext, pAd->bulkResetPipeid, pHTTXContext->BulkOutSize, (usb_complete_t)RTUSBBulkOutDataPacketComplete); if((ret = RTUSB_SUBMIT_URB(pHTTXContext->pUrb))!=0) { RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); pAd->BulkOutPending[pAd->bulkResetPipeid] = FALSE; pHTTXContext->IRPPending = FALSE; pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 0; RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); DBGPRINT(RT_DEBUG_ERROR, ("CmdThread : CMDTHREAD_RESET_BULK_OUT: Submit Tx URB failed %d\n", ret)); } else { RTMP_IRQ_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); DBGPRINT_RAW(RT_DEBUG_TRACE,("\tCMDTHREAD_RESET_BULK_OUT: TxContext[%d]:CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, pending=%d!\n", pAd->bulkResetPipeid, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad, pAd->BulkOutPending[pAd->bulkResetPipeid])); DBGPRINT_RAW(RT_DEBUG_TRACE,("\t\tBulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther)); RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); DBGPRINT_RAW(RT_DEBUG_TRACE, ("\tCMDTHREAD_RESET_BULK_OUT: Submit Tx DATA URB for failed BulkReq(0x%lx) Done, status=%d!\n", pAd->bulkResetReq[pAd->bulkResetPipeid], pHTTXContext->pUrb->status)); } } } else { //NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); //RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); DBGPRINT_RAW(RT_DEBUG_ERROR, ("CmdThread : TX DATA RECOVER FAIL for BulkReq(0x%lx) because BulkOutPending[%d] is TRUE!\n", pAd->bulkResetReq[pAd->bulkResetPipeid], pAd->bulkResetPipeid)); if (pAd->bulkResetPipeid == 0) { UCHAR pendingContext = 0; PHT_TX_CONTEXT pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[pAd->bulkResetPipeid ]); PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa); PTX_CONTEXT pNULLContext = (PTX_CONTEXT)(&pAd->PsPollContext); PTX_CONTEXT pPsPollContext = (PTX_CONTEXT)(&pAd->NullContext); if (pHTTXContext->IRPPending) pendingContext |= 1; else if (pMLMEContext->IRPPending) pendingContext |= 2; else if (pNULLContext->IRPPending) pendingContext |= 4; else if (pPsPollContext->IRPPending) pendingContext |= 8; else pendingContext = 0; DBGPRINT_RAW(RT_DEBUG_ERROR, ("\tTX Occupied by %d!\n", pendingContext)); } // no matter what, clean the flag RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << pAd->bulkResetPipeid)); } RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); //RTUSBKickBulkOut(pAd); } } /* // Don't cancel BULKIN. while ((atomic_read(&pAd->PendingRx) > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { if (atomic_read(&pAd->PendingRx) > 0) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkIn IRP Pending!!cancel it!\n")); RTUSBCancelPendingBulkInIRP(pAd); } RTMPusecDelay(100000); } if ((atomic_read(&pAd->PendingRx) == 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { UCHAR i; RTUSBRxPacket(pAd); pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index pAd->NextRxBulkInIndex = 0; // Rx Bulk pointer for (i = 0; i < (RX_RING_SIZE); i++) { PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); pRxContext->pAd = pAd; pRxContext->InUse = FALSE; pRxContext->IRPPending = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -