/* ************************************************************************* * 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: rtusb_io.c Abstract: Revision History: Who When What -------- ---------- ---------------------------------------------- Name Date Modification logs Paul Lin 06-25-2004 created */ #ifdef RTMP_MAC_USB #include "../rt_config.h" /* ======================================================================== Routine Description: NIC initialization complete Arguments: Return Value: IRQL = Note: ======================================================================== */ static int RTUSBFirmwareRun(struct rt_rtmp_adapter *pAd) { int Status; Status = RTUSB_VendorRequest(pAd, USBD_TRANSFER_DIRECTION_OUT, DEVICE_VENDOR_REQUEST_OUT, 0x01, 0x8, 0, NULL, 0); return Status; } /* ======================================================================== Routine Description: Write Firmware to NIC. Arguments: Return Value: IRQL = Note: ======================================================================== */ int RTUSBFirmwareWrite(struct rt_rtmp_adapter *pAd, const u8 *pFwImage, unsigned long FwLen) { u32 MacReg; int Status; /* unsigned long i; */ u16 writeLen; Status = RTUSBReadMACRegister(pAd, MAC_CSR0, &MacReg); writeLen = FwLen; RTUSBMultiWrite(pAd, FIRMWARE_IMAGE_BASE, pFwImage, writeLen); Status = RTUSBWriteMACRegister(pAd, 0x7014, 0xffffffff); Status = RTUSBWriteMACRegister(pAd, 0x701c, 0xffffffff); Status = RTUSBFirmwareRun(pAd); /*2008/11/28:KH add to fix the dead rf frequency offset bug<-- */ RTMPusecDelay(10000); RTUSBWriteMACRegister(pAd, H2M_MAILBOX_CSR, 0); AsicSendCommandToMcu(pAd, 0x72, 0x00, 0x00, 0x00); /*reset rf by MCU supported by new firmware */ /*2008/11/28:KH add to fix the dead rf frequency offset bug--> */ return Status; } int RTUSBVenderReset(struct rt_rtmp_adapter *pAd) { int Status; DBGPRINT_RAW(RT_DEBUG_ERROR, ("-->RTUSBVenderReset\n")); Status = RTUSB_VendorRequest(pAd, USBD_TRANSFER_DIRECTION_OUT, DEVICE_VENDOR_REQUEST_OUT, 0x01, 0x1, 0, NULL, 0); DBGPRINT_RAW(RT_DEBUG_ERROR, ("<--RTUSBVenderReset\n")); return Status; } /* ======================================================================== Routine Description: Read various length data from RT2573 Arguments: Return Value: IRQL = Note: ======================================================================== */ int RTUSBMultiRead(struct rt_rtmp_adapter *pAd, u16 Offset, u8 *pData, u16 length) { int Status; Status = RTUSB_VendorRequest(pAd, (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK), DEVICE_VENDOR_REQUEST_IN, 0x7, 0, Offset, pData, length); return Status; } /* ======================================================================== Routine Description: Write various length data to RT2573 Arguments: Return Value: IRQL = Note: ======================================================================== */ int RTUSBMultiWrite_OneByte(struct rt_rtmp_adapter *pAd, u16 Offset, const u8 *pData) { int Status; /* TODO: In 2870, use this funciton carefully cause it's not stable. */ Status = RTUSB_VendorRequest(pAd, USBD_TRANSFER_DIRECTION_OUT, DEVICE_VENDOR_REQUEST_OUT, 0x6, 0, Offset, (u8 *)pData, 1); return Status; } int RTUSBMultiWrite(struct rt_rtmp_adapter *pAd, u16 Offset, const u8 *pData, u16 length) { int Status; u16 index = 0, Value; const u8 *pSrc = pData; u16 resude = 0; resude = length % 2; length += resude; do { Value = (u16)(*pSrc | (*(pSrc + 1) << 8)); Status = RTUSBSingleWrite(pAd, Offset + index, Value); index += 2; length -= 2; pSrc = pSrc + 2; } while (length > 0); return Status; } int RTUSBSingleWrite(struct rt_rtmp_adapter *pAd, u16 Offset, u16 Value) { int Status; Status = RTUSB_VendorRequest(pAd, USBD_TRANSFER_DIRECTION_OUT, DEVICE_VENDOR_REQUEST_OUT, 0x2, Value, Offset, NULL, 0); return Status; } /* ======================================================================== Routine Description: Read 32-bit MAC register Arguments: Return Value: IRQL = Note: ======================================================================== */ int RTUSBReadMACRegister(struct rt_rtmp_adapter *pAd, u16 Offset, u32 *pValue) { int Status = 0; u32 localVal; Status = RTUSB_VendorRequest(pAd, (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK), DEVICE_VENDOR_REQUEST_IN, 0x7, 0, Offset, &localVal, 4); *pValue = le2cpu32(localVal); if (Status < 0) *pValue = 0xffffffff; return Status; } /* ======================================================================== Routine Description: Write 32-bit MAC register Arguments: Return Value: IRQL = Note: ======================================================================== */ int RTUSBWriteMACRegister(struct rt_rtmp_adapter *pAd, u16 Offset, u32 Value) { int Status; u32 localVal; localVal = Value; Status = RTUSBSingleWrite(pAd, Offset, (u16)(localVal & 0xffff)); Status = RTUSBSingleWrite(pAd, Offset + 2, (u16)((localVal & 0xffff0000) >> 16)); return Status; } /* ======================================================================== Routine Description: Read 8-bit BBP register Arguments: Return Value: IRQL = Note: ======================================================================== */ int RTUSBReadBBPRegister(struct rt_rtmp_adapter *pAd, u8 Id, u8 *pValue) { BBP_CSR_CFG_STRUC BbpCsr; u32 i = 0; int status; /* Verify the busy condition */ do { status = RTUSBReadMACRegister(pAd, BBP_CSR_CFG, &BbpCsr.word); if (status >= 0) { if (!(BbpCsr.field.Busy == BUSY)) break; } DBGPRINT(RT_DEBUG_TRACE, ("RTUSBReadBBPRegister(BBP_CSR_CFG_1):retry count=%d!\n", i)); i++; } while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { /* */ /* Read failed then Return Default value. */ /* */ *pValue = pAd->BbpWriteLatch[Id]; DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); return STATUS_UNSUCCESSFUL; } /* Prepare for write material */ BbpCsr.word = 0; BbpCsr.field.fRead = 1; BbpCsr.field.Busy = 1; BbpCsr.field.RegNum = Id; RTUSBWriteMACRegister(pAd, BBP_CSR_CFG, BbpCsr.word); i = 0; /* Verify the busy condition */ do { status = RTUSBReadMACRegister(pAd, BBP_CSR_CFG, &BbpCsr.word); if (status >= 0) { if (!(BbpCsr.field.Busy == BUSY)) { *pValue = (u8)BbpCsr.field.Value; break; } } DBGPRINT(RT_DEBUG_TRACE, ("RTUSBReadBBPRegister(BBP_CSR_CFG_2):retry count=%d!\n", i)); i++; } while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { /* */ /* Read failed then Return Default value. */ /* */ *pValue = pAd->BbpWriteLatch[Id]; DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; } /* ======================================================================== Routine Description: Write 8-bit BBP register Arguments: Return Value: IRQL = Note: ======================================================================== */ int RTUSBWriteBBPRegister(struct rt_rtmp_adapter *pAd, u8 Id, u8 Value) { BBP_CSR_CFG_STRUC BbpCsr; u32 i = 0; int status; /* Verify the busy condition */ do { status = RTUSBReadMACRegister(pAd, BBP_CSR_CFG, &BbpCsr.word); if (status >= 0) { if (!(BbpCsr.field.Busy == BUSY)) break; } DBGPRINT(RT_DEBUG_TRACE, ("RTUSBWriteBBPRegister(BBP_CSR_CFG):retry count=%d!\n", i)); i++; } while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); return STATUS_UNSUCCESSFUL; } /* Prepare for write material */ BbpCsr.word = 0; BbpCsr.field.fRead = 0; BbpCsr.field.Value = Value; BbpCsr.field.Busy = 1; BbpCsr.field.RegNum = Id; RTUSBWriteMACRegister(pAd, BBP_CSR_CFG, BbpCsr.word); pAd->BbpWriteLatch[Id] = Value; return STATUS_SUCCESS; } /* ======================================================================== Routine Description: Write RF register through MAC Arguments: Return Value: IRQL = Note: ======================================================================== */ int RTUSBWriteRFRegister(struct rt_rtmp_adapter *pAd, u32 Value) { PHY_CSR4_STRUC PhyCsr4; u32 i = 0; int status; NdisZeroMemory(&PhyCsr4, sizeof(PHY_CSR4_STRUC)); do { status = RTUSBReadMACRegister(pAd, RF_CSR_CFG0, &PhyCsr4.word); if (status >= 0) { if (!(PhyCsr4.field.Busy)) break; } DBGPRINT(RT_DEBUG_TRACE, ("RTUSBWriteRFRegister(RF_CSR_CFG0):retry count=%d!\n", i)); i++; } while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))); if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n")); return STATUS_UNSUCCESSFUL; } RTUSBWriteMACRegister(pAd, RF_CSR_CFG0, Value); return STATUS_SUCCESS; } /* ======================================================================== Routine Description: Arguments: Return Value: IRQL = Note: ======================================================================== */ int RTUSBReadEEPROM(struct rt_rtmp_adapter *pAd, u16 Offset, u8 *pData, u16 length) { int Status = STATUS_SUCCESS; Status = RTUSB_VendorRequest(pAd, (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK), DEVICE_VENDOR_REQUEST_IN, 0x9, 0, Offset, pData, length); return Status; } /* ======================================================================== Routine Description: Arguments: Return Value: IRQL = Note: ======================================================================== */ int RTUSBWriteEEPROM(struct rt_rtmp_adapter *pAd, u16 Offset, u8 *pData, u16 length) { int Status = STATUS_SUCCESS; Status = RTUSB_VendorRequest(pAd, USBD_TRANSFER_DIRECTION_OUT, DEVICE_VENDOR_REQUEST_OUT, 0x8, 0, Offset, pData, length); return Status; } int RTUSBReadEEPROM16(struct rt_rtmp_adapter *pAd, u16 offset, u16 *pData) { int status; u16 localData; status = RTUSBReadEEPROM(pAd, offset, (u8 *)(&localData), 2); if (status == STATUS_SUCCESS) *pData = le2cpu16(localData); return status; } /* ======================================================================== Routine Description: Arguments: Return Value: IRQL = Note: ======================================================================== */ void RTUSBPutToSleep(struct rt_rtmp_adapter *pAd) { u32 value; /* Timeout 0x40 x 50us */ value = (SLEEPCID << 16) + (OWNERMCU << 24) + (0x40 << 8) + 1; RTUSBWriteMACRegister(pAd, 0x7010, value); RTUSBWriteMACRegister(pAd, 0x404, 0x30); /*RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); */ DBGPRINT_RAW(RT_DEBUG_ERROR, ("Sleep Mailbox testvalue %x\n", value)); } /* ======================================================================== Routine Description: Arguments: Return Value: IRQL = Note: ======================================================================== */ int RTUSBWakeUp(struct rt_rtmp_adapter *pAd) { int Status; Status = RTUSB_VendorRequest(pAd, USBD_TRANSFER_DIRECTION_OUT, DEVICE_VENDOR_REQUEST_OUT, 0x01, 0x09, 0, NULL, 0); return Status; } /* ======================================================================== Routine Description: Arguments: Return Value: IRQL = Note: ======================================================================== */ void RTUSBInitializeCmdQ(struct rt_cmdq *cmdq) { cmdq->head = NULL; cmdq->tail = NULL; cmdq->size = 0; cmdq->CmdQState = RTMP_TASK_STAT_INITED; } /* ======================================================================== Routine Description: Arguments: Return Value: IRQL = Note: ======================================================================== */ int RTUSBEnqueueCmdFromNdis(struct rt_rtmp_adapter *pAd, IN NDIS_OID Oid, IN BOOLEAN SetInformation, void *pInformationBuffer, u32 InformationBufferLength) { int status; struct rt_cmdqelmt *cmdqelmt = NULL; struct rt_rtmp_os_task *pTask = &pAd->cmdQTask; #ifdef KTHREAD_SUPPORT if (pTask->kthread_task == NULL) #else CHECK_PID_LEGALITY(pTask->taskPID) { } else #endif return NDIS_STATUS_RESOURCES; status = os_alloc_mem(pAd, (u8 **) (&cmdqelmt), sizeof(struct rt_cmdqelmt)); if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt == NULL)) return NDIS_STATUS_RESOURCES; cmdqelmt->buffer = NULL; if (pInformationBuffer != NULL) { status = os_alloc_mem(pAd, (u8 **) & cmdqelmt->buffer, InformationBufferLength); if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt->buffer == NULL)) { kfree(cmdqelmt); return NDIS_STATUS_RESOURCES; } else { NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, InformationBufferLength); cmdqelmt->bufferlength = InformationBufferLength; } } else cmdqelmt->bufferlength = 0; cmdqelmt->command = Oid; cmdqelmt->CmdFromNdis = TRUE; if (SetInformation == TRUE) cmdqelmt->SetOperation = TRUE; else cmdqelmt->SetOperation = FALSE; NdisAcquireSpinLock(&pAd->CmdQLock); if (pAd->CmdQ.CmdQState & RTMP_TASK_CAN_DO_INSERT) { EnqueueCmd((&pAd->CmdQ), cmdqelmt); status = NDIS_STATUS_SUCCESS; } else { status = NDIS_STATUS_FAILURE; } NdisReleaseSpinLock(&pAd->CmdQLock); if (status == NDIS_STATUS_FAILURE) { if (cmdqelmt->buffer) os_free_mem(pAd, cmdqelmt->buffer); os_free_mem(pAd, cmdqelmt); } else RTUSBCMDUp(pAd); return NDIS_STATUS_SUCCESS; } /* ======================================================================== Routine Description: Arguments: Return Value: IRQL = Note: ======================================================================== */ int RTUSBEnqueueInternalCmd(struct rt_rtmp_adapter *pAd, IN NDIS_OID Oid, void *pInformationBuffer, u32 InformationBufferLength) { int status; struct rt_cmdqelmt *cmdqelmt = NULL; status = os_alloc_mem(pAd, (u8 **) & cmdqelmt, sizeof(struct rt_cmdqelmt)); if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt == NULL)) return NDIS_STATUS_RESOURCES; NdisZeroMemory(cmdqelmt, sizeof(struct rt_cmdqelmt)); if (InformationBufferLength > 0) { status = os_alloc_mem(pAd, (u8 **) & cmdqelmt->buffer, InformationBufferLength); if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt->buffer == NULL)) { os_free_mem(pAd, cmdqelmt); return NDIS_STATUS_RESOURCES; } else { NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, InformationBufferLength); cmdqelmt->bufferlength = InformationBufferLength; } } else { cmdqelmt->buffer = NULL; cmdqelmt->bufferlength = 0; } cmdqelmt->command = Oid; cmdqelmt->CmdFromNdis = FALSE; if (cmdqelmt != NULL) { NdisAcquireSpinLock(&pAd->CmdQLock); if (pAd->CmdQ.CmdQState & RTMP_TASK_CAN_DO_INSERT) { EnqueueCmd((&pAd->CmdQ), cmdqelmt); status = NDIS_STATUS_SUCCESS; } else { status = NDIS_STATUS_FAILURE; } NdisReleaseSpinLock(&pAd->CmdQLock); if (status == NDIS_STATUS_FAILURE) { if (cmdqelmt->buffer) os_free_mem(pAd, cmdqelmt->buffer); os_free_mem(pAd, cmdqelmt); } else RTUSBCMDUp(pAd); } return NDIS_STATUS_SUCCESS; } /* ======================================================================== Routine Description: Arguments: Return Value: IRQL = Note: ======================================================================== */ void RTUSBDequeueCmd(struct rt_cmdq *cmdq, struct rt_cmdqelmt * * 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: ======================================================================== */ int RTUSB_VendorRequest(struct rt_rtmp_adapter *pAd, u32 TransferFlags, u8 RequestType, u8 Request, u16 Value, u16 Index, void *TransferBuffer, u32 TransferBufferLength) { int ret = 0; struct os_cookie *pObj = (struct os_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; 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); } 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)); if ((pAd->UsbVendorReqBuf) && (RequestType == DEVICE_VENDOR_REQUEST_IN)) NdisMoveMemory(TransferBuffer, tmpBuf, TransferBufferLength); up(&(pAd->UsbVendorReq_semaphore)); if (ret < 0) { 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: ======================================================================== */ int RTUSB_ResetDevice(struct rt_rtmp_adapter *pAd) { int Status = TRUE; DBGPRINT_RAW(RT_DEBUG_TRACE, ("--->USB_ResetDevice\n")); /*RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS); */ return Status; } void CMDHandler(struct rt_rtmp_adapter *pAd) { struct rt_cmdqelmt *cmdqelmt; u8 *pData; int NdisStatus = NDIS_STATUS_SUCCESS; /* unsigned long Now = 0; */ int 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: { u32 data; { /* 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; } } } } break; case CMDTHREAD_QKERIODIC_EXECUT: { StaQuickResponeForRateUpExec(NULL, pAd, NULL, NULL); } break; case CMDTHREAD_RESET_BULK_OUT: { u32 MACValue; u8 Index; int ret = 0; struct rt_ht_tx_context *pHTTXContext; /* struct rt_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); { RTUSBInitHTTxDesc (pAd, pHTTXContext, pAd-> bulkResetPipeid, pHTTXContext-> BulkOutSize, (usb_complete_t) RTUSBBulkOutDataPacketComplete); ret = RTUSB_SUBMIT_URB (pHTTXContext-> pUrb); if (ret != 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) { u8 pendingContext = 0; struct rt_ht_tx_context * pHTTXContext = (struct rt_ht_tx_context *) (&pAd-> TxContext [pAd-> bulkResetPipeid]); struct rt_tx_context * pMLMEContext = (struct rt_tx_context *) (pAd-> MgmtRing. Cell[pAd-> MgmtRing. TxDmaIdx]. AllocVa); struct rt_tx_context * pNULLContext = (struct rt_tx_context *) (&pAd-> PsPollContext); struct rt_tx_context * pPsPollContext = (struct rt_tx_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))) { u8 i; RTUSBRxPacket(pAd); pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index pAd->NextRxBulkInIndex = 0; // Rx Bulk pointer for (i = 0; i < (RX_RING_SIZE); i++) { struct rt_rx_context *pRxContext = &(pAd->RxContext[i]); pRxContext->pAd = pAd; pRxContext->InUse = FALSE; pRxContext->IRPPending = FALSE; pRxContext->Readable = FALSE; pRxContext->ReorderInUse = FALSE; } RTUSBBulkReceive(pAd); DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTUSBBulkReceive\n")); } */ DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_OUT<===\n")); break; case CMDTHREAD_RESET_BULK_IN: DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN === >\n")); /* All transfers must be aborted or cancelled before attempting to reset the pipe. */ { u32 MACValue; { /*while ((atomic_read(&pAd->PendingRx) > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) */ if ((pAd->PendingRx > 0) && (!RTMP_TEST_FLAG (pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { DBGPRINT_RAW (RT_DEBUG_ERROR, ("BulkIn IRP Pending!!!\n")); RTUSBCancelPendingBulkInIRP (pAd); RTMPusecDelay(100000); pAd->PendingRx = 0; } } /* Wait 10ms before reading register. */ RTMPusecDelay(10000); ntStatus = RTUSBReadMACRegister(pAd, MAC_CSR0, &MACValue); if ((NT_SUCCESS(ntStatus) == TRUE) && (!(RTMP_TEST_FLAG (pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))))) { u8 i; if (RTMP_TEST_FLAG (pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))) break; pAd->NextRxBulkInPosition = pAd->RxContext[pAd-> NextRxBulkInIndex]. BulkInOffset; DBGPRINT(RT_DEBUG_TRACE, ("BULK_IN_RESET: NBIIdx=0x%x,NBIRIdx=0x%x, BIRPos=0x%lx. BIReq=x%lx, BIComplete=0x%lx, BICFail0x%lx\n", pAd-> NextRxBulkInIndex, pAd-> NextRxBulkInReadIndex, pAd-> NextRxBulkInPosition, pAd->BulkInReq, pAd->BulkInComplete, pAd-> BulkInCompleteFail)); for (i = 0; i < RX_RING_SIZE; i++) { DBGPRINT(RT_DEBUG_TRACE, ("\tRxContext[%d]: IRPPending=%d, InUse=%d, Readable=%d!\n", i, pAd-> RxContext[i]. IRPPending, pAd-> RxContext[i]. InUse, pAd-> RxContext[i]. Readable)); } /* DBGPRINT_RAW(RT_DEBUG_ERROR, ("==========================================\n")); pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index pAd->NextRxBulkInIndex = 0; // Rx Bulk pointer for (i = 0; i < (RX_RING_SIZE); i++) { struct rt_rx_context *pRxContext = &(pAd->RxContext[i]); pRxContext->pAd = pAd; pRxContext->InUse = FALSE; pRxContext->IRPPending = FALSE; pRxContext->Readable = FALSE; pRxContext->ReorderInUse = FALSE; } */ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); for (i = 0; i < pAd->CommonCfg. NumOfBulkInIRP; i++) { /*RTUSBBulkReceive(pAd); */ struct rt_rx_context *pRxContext; PURB pUrb; int ret = 0; unsigned long IrqFlags; RTMP_IRQ_LOCK(&pAd-> BulkInLock, IrqFlags); pRxContext = &(pAd-> RxContext[pAd-> NextRxBulkInIndex]); if ((pAd->PendingRx > 0) || (pRxContext-> Readable == TRUE) || (pRxContext-> InUse == TRUE)) { RTMP_IRQ_UNLOCK (&pAd-> BulkInLock, IrqFlags); break; } pRxContext->InUse = TRUE; pRxContext->IRPPending = TRUE; pAd->PendingRx++; pAd->BulkInReq++; RTMP_IRQ_UNLOCK(&pAd-> BulkInLock, IrqFlags); /* Init Rx context descriptor */ RTUSBInitRxDesc(pAd, pRxContext); pUrb = pRxContext->pUrb; ret = RTUSB_SUBMIT_URB(pUrb); if (ret != 0) { /* fail */ RTMP_IRQ_LOCK (&pAd-> BulkInLock, IrqFlags); pRxContext-> InUse = FALSE; pRxContext-> IRPPending = FALSE; pAd-> PendingRx--; pAd-> BulkInReq--; RTMP_IRQ_UNLOCK (&pAd-> BulkInLock, IrqFlags); DBGPRINT (RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB failed(%d), status=%d\n", ret, pUrb-> status)); } else { /* success */ /*DBGPRINT(RT_DEBUG_TRACE, ("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", */ /* pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex)); */ DBGPRINT_RAW (RT_DEBUG_TRACE, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB Done, status=%d!\n", pUrb-> status)); ASSERT((pRxContext->InUse == pRxContext->IRPPending)); } } } else { /* Card must be removed */ if (NT_SUCCESS(ntStatus) != TRUE) { RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); DBGPRINT_RAW (RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Read Register Failed!Card must be removed!!\n\n")); } else { DBGPRINT_RAW (RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Cannot do bulk in because flags(0x%lx) on !\n", pAd->Flags)); } } } DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN <===\n")); break; case CMDTHREAD_SET_ASIC_WCID: { struct rt_set_asic_wcid SetAsicWcid; u16 offset; u32 MACValue, MACRValue = 0; SetAsicWcid = *((struct rt_set_asic_wcid *)(pData)); if (SetAsicWcid.WCID >= MAX_LEN_OF_MAC_TABLE) return; offset = MAC_WCID_BASE + ((u8)SetAsicWcid.WCID) * HW_WCID_ENTRY_SIZE; DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_SET_ASIC_WCID : WCID = %ld, SetTid = %lx, DeleteTid = %lx.\n", SetAsicWcid.WCID, SetAsicWcid.SetTid, SetAsicWcid.DeleteTid)); MACValue = (pAd->MacTab. Content[SetAsicWcid.WCID]. Addr[3] << 24) + (pAd->MacTab. Content[SetAsicWcid.WCID]. Addr[2] << 16) + (pAd->MacTab. Content[SetAsicWcid.WCID]. Addr[1] << 8) + (pAd->MacTab. Content[SetAsicWcid.WCID].Addr[0]); DBGPRINT_RAW(RT_DEBUG_TRACE, ("1-MACValue= %x,\n", MACValue)); RTUSBWriteMACRegister(pAd, offset, MACValue); /* Read bitmask */ RTUSBReadMACRegister(pAd, offset + 4, &MACRValue); if (SetAsicWcid.DeleteTid != 0xffffffff) MACRValue &= (~SetAsicWcid.DeleteTid); if (SetAsicWcid.SetTid != 0xffffffff) MACRValue |= (SetAsicWcid.SetTid); MACRValue &= 0xffff0000; MACValue = (pAd->MacTab. Content[SetAsicWcid.WCID]. Addr[5] << 8) + pAd->MacTab.Content[SetAsicWcid. WCID].Addr[4]; MACValue |= MACRValue; RTUSBWriteMACRegister(pAd, offset + 4, MACValue); DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-MACValue= %x,\n", MACValue)); } break; case CMDTHREAD_SET_ASIC_WCID_CIPHER: { struct rt_set_asic_wcid_attri SetAsicWcidAttri; u16 offset; u32 MACRValue = 0; SHAREDKEY_MODE_STRUC csr1; SetAsicWcidAttri = *((struct rt_set_asic_wcid_attri *) (pData)); if (SetAsicWcidAttri.WCID >= MAX_LEN_OF_MAC_TABLE) return; offset = MAC_WCID_ATTRIBUTE_BASE + ((u8)SetAsicWcidAttri.WCID) * HW_WCID_ATTRI_SIZE; DBGPRINT_RAW(RT_DEBUG_TRACE, ("Cmd : CMDTHREAD_SET_ASIC_WCID_CIPHER : WCID = %ld, Cipher = %lx.\n", SetAsicWcidAttri.WCID, SetAsicWcidAttri.Cipher)); /* Read bitmask */ RTUSBReadMACRegister(pAd, offset, &MACRValue); MACRValue = 0; MACRValue |= (((u8)SetAsicWcidAttri. Cipher) << 1); RTUSBWriteMACRegister(pAd, offset, MACRValue); DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-offset = %x , MACValue= %x,\n", offset, MACRValue)); offset = PAIRWISE_IVEIV_TABLE_BASE + ((u8)SetAsicWcidAttri.WCID) * HW_IVEIV_ENTRY_SIZE; MACRValue = 0; if ((SetAsicWcidAttri.Cipher <= CIPHER_WEP128)) MACRValue |= (pAd->StaCfg. DefaultKeyId << 30); else MACRValue |= (0x20000000); RTUSBWriteMACRegister(pAd, offset, MACRValue); DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-offset = %x , MACValue= %x,\n", offset, MACRValue)); /* */ /* Update cipher algorithm. WSTA always use BSS0 */ /* */ /* for adhoc mode only ,because wep status slow than add key, when use zero config */ if (pAd->StaCfg.BssType == BSS_ADHOC) { offset = MAC_WCID_ATTRIBUTE_BASE; RTUSBReadMACRegister(pAd, offset, &MACRValue); MACRValue &= (~0xe); MACRValue |= (((u8)SetAsicWcidAttri. Cipher) << 1); RTUSBWriteMACRegister(pAd, offset, MACRValue); /*Update group key cipher,,because wep status slow than add key, when use zero config */ RTUSBReadMACRegister(pAd, SHARED_KEY_MODE_BASE + 4 * (0 / 2), &csr1. word); csr1.field.Bss0Key0CipherAlg = SetAsicWcidAttri.Cipher; csr1.field.Bss0Key1CipherAlg = SetAsicWcidAttri.Cipher; RTUSBWriteMACRegister(pAd, SHARED_KEY_MODE_BASE + 4 * (0 / 2), csr1. word); } } break; /*Benson modified for USB interface, avoid in interrupt when write key, 20080724 --> */ case RT_CMD_SET_KEY_TABLE: /*General call for AsicAddPairwiseKeyEntry() */ { struct rt_add_pairwise_key_entry KeyInfo; KeyInfo = *((struct rt_add_pairwise_key_entry *) (pData)); AsicAddPairwiseKeyEntry(pAd, KeyInfo.MacAddr, (u8)KeyInfo. MacTabMatchWCID, &KeyInfo. CipherKey); } break; case RT_CMD_SET_RX_WCID_TABLE: /*General call for RTMPAddWcidAttributeEntry() */ { struct rt_mac_table_entry *pEntry; u8 KeyIdx = 0; u8 CipherAlg = CIPHER_NONE; u8 ApIdx = BSS0; pEntry = (struct rt_mac_table_entry *)(pData); RTMPAddWcidAttributeEntry(pAd, ApIdx, KeyIdx, CipherAlg, pEntry); } break; /*Benson modified for USB interface, avoid in interrupt when write key, 20080724 <-- */ case CMDTHREAD_SET_CLIENT_MAC_ENTRY: { struct rt_mac_table_entry *pEntry; pEntry = (struct rt_mac_table_entry *)pData; { AsicRemovePairwiseKeyEntry(pAd, pEntry-> apidx, (u8) pEntry-> Aid); if ((pEntry->AuthMode <= Ndis802_11AuthModeAutoSwitch) && (pEntry->WepStatus == Ndis802_11Encryption1Enabled)) { u32 uIV = 1; u8 *ptr; ptr = (u8 *)& uIV; *(ptr + 3) = (pAd->StaCfg. DefaultKeyId << 6); AsicUpdateWCIDIVEIV(pAd, pEntry-> Aid, uIV, 0); AsicUpdateWCIDAttribute (pAd, pEntry->Aid, BSS0, pAd-> SharedKey[BSS0] [pAd->StaCfg. DefaultKeyId]. CipherAlg, FALSE); } else if (pEntry->AuthMode == Ndis802_11AuthModeWPANone) { u32 uIV = 1; u8 *ptr; ptr = (u8 *)& uIV; *(ptr + 3) = (pAd->StaCfg. DefaultKeyId << 6); AsicUpdateWCIDIVEIV(pAd, pEntry-> Aid, uIV, 0); AsicUpdateWCIDAttribute (pAd, pEntry->Aid, BSS0, pAd-> SharedKey[BSS0] [pAd->StaCfg. DefaultKeyId]. CipherAlg, FALSE); } else { /* */ /* Other case, disable engine. */ /* Don't worry WPA key, we will add WPA Key after 4-Way handshaking. */ /* */ u16 offset; offset = MAC_WCID_ATTRIBUTE_BASE + (pEntry->Aid * HW_WCID_ATTRI_SIZE); /* RX_PKEY_MODE:0 for no security; RX_KEY_TAB:0 for shared key table; BSS_IDX:0 */ RTUSBWriteMACRegister (pAd, offset, 0); } } AsicUpdateRxWCIDTable(pAd, pEntry->Aid, pEntry->Addr); DBGPRINT(RT_DEBUG_TRACE, ("UpdateRxWCIDTable(): Aid=%d, " "Addr=%pM!\n", pEntry->Aid, pEntry->Addr)); } break; /* add by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet */ case CMDTHREAD_UPDATE_PROTECT: { AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT), TRUE, 0); } break; /* end johnli */ case OID_802_11_ADD_WEP: { u32 i; u32 KeyIdx; struct rt_ndis_802_11_wep *pWepKey; DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::OID_802_11_ADD_WEP \n")); pWepKey = (struct rt_ndis_802_11_wep *)pData; KeyIdx = pWepKey->KeyIndex & 0x0fffffff; /* it is a shared key */ if ((KeyIdx >= 4) || ((pWepKey->KeyLength != 5) && (pWepKey->KeyLength != 13))) { NdisStatus = NDIS_STATUS_INVALID_DATA; DBGPRINT(RT_DEBUG_ERROR, ("CmdThread::OID_802_11_ADD_WEP, INVALID_DATA!!\n")); } else { u8 CipherAlg; pAd->SharedKey[BSS0][KeyIdx]. KeyLen = (u8)pWepKey->KeyLength; NdisMoveMemory(pAd-> SharedKey[BSS0] [KeyIdx].Key, &pWepKey-> KeyMaterial, pWepKey-> KeyLength); CipherAlg = (pAd-> SharedKey[BSS0][KeyIdx]. KeyLen == 5) ? CIPHER_WEP64 : CIPHER_WEP128; /* */ /* Change the WEP cipher to CKIP cipher if CKIP KP on. */ /* Funk UI or Meetinghouse UI will add ckip key from this path. */ /* */ if (pAd->OpMode == OPMODE_STA) { pAd->MacTab. Content[BSSID_WCID]. PairwiseKey. CipherAlg = pAd-> SharedKey[BSS0] [KeyIdx].CipherAlg; pAd->MacTab. Content[BSSID_WCID]. PairwiseKey.KeyLen = pAd-> SharedKey[BSS0] [KeyIdx].KeyLen; } pAd->SharedKey[BSS0][KeyIdx]. CipherAlg = CipherAlg; if (pWepKey-> KeyIndex & 0x80000000) { /* Default key for tx (shared key) */ u8 IVEIV[8]; u32 WCIDAttri, Value; u16 offset, offset2; NdisZeroMemory(IVEIV, 8); pAd->StaCfg. DefaultKeyId = (u8)KeyIdx; /* Add BSSID to WCTable. because this is Tx wep key. */ /* WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:1=PAIRWISE KEY, BSSIdx is 0 */ WCIDAttri = (CipherAlg << 1) | SHAREDKEYTABLE; offset = MAC_WCID_ATTRIBUTE_BASE + (BSSID_WCID * HW_WCID_ATTRI_SIZE); RTUSBWriteMACRegister (pAd, offset, WCIDAttri); /* 1. IV/EIV */ /* Specify key index to find shared key. */ IVEIV[3] = (u8)(KeyIdx << 6); /*WEP Eiv bit off. groupkey index is not 0 */ offset = PAIRWISE_IVEIV_TABLE_BASE + (BSS0Mcast_WCID * HW_IVEIV_ENTRY_SIZE); offset2 = PAIRWISE_IVEIV_TABLE_BASE + (BSSID_WCID * HW_IVEIV_ENTRY_SIZE); for (i = 0; i < 8;) { Value = IVEIV[i]; Value += (IVEIV [i + 1] << 8); Value += (IVEIV [i + 2] << 16); Value += (IVEIV [i + 3] << 24); RTUSBWriteMACRegister (pAd, offset + i, Value); RTUSBWriteMACRegister (pAd, offset2 + i, Value); i += 4; } /* 2. WCID Attribute UDF:3, BSSIdx:3, Alg:3, Keytable:use share key, BSSIdx is 0 */ WCIDAttri = (pAd-> SharedKey[BSS0] [KeyIdx]. CipherAlg << 1) | SHAREDKEYTABLE; offset = MAC_WCID_ATTRIBUTE_BASE + (BSS0Mcast_WCID * HW_WCID_ATTRI_SIZE); DBGPRINT(RT_DEBUG_TRACE, ("BSS0Mcast_WCID : offset = %x, WCIDAttri = %x\n", offset, WCIDAttri)); RTUSBWriteMACRegister (pAd, offset, WCIDAttri); } AsicAddSharedKeyEntry(pAd, BSS0, (u8) KeyIdx, CipherAlg, pWepKey-> KeyMaterial, NULL, NULL); DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::OID_802_11_ADD_WEP (KeyIdx=%d, Len=%d-byte)\n", KeyIdx, pWepKey->KeyLength)); } } break; case CMDTHREAD_802_11_COUNTER_MEASURE: break; case CMDTHREAD_SET_GROUP_KEY: WpaStaGroupKeySetting(pAd); break; case CMDTHREAD_SET_PAIRWISE_KEY: WpaStaPairwiseKeySetting(pAd); break; case CMDTHREAD_SET_PSM_BIT: { u16 *pPsm = (u16 *) pData; MlmeSetPsmBit(pAd, *pPsm); } break; case CMDTHREAD_FORCE_WAKE_UP: AsicForceWakeup(pAd, TRUE); break; default: DBGPRINT(RT_DEBUG_ERROR, ("--> Control Thread !! ERROR !! Unknown(cmdqelmt->command=0x%x) !! \n", cmdqelmt->command)); break; } } if (cmdqelmt->CmdFromNdis == TRUE) { if (cmdqelmt->buffer != NULL) os_free_mem(pAd, cmdqelmt->buffer); os_free_mem(pAd, cmdqelmt); } else { if ((cmdqelmt->buffer != NULL) && (cmdqelmt->bufferlength != 0)) os_free_mem(pAd, cmdqelmt->buffer); os_free_mem(pAd, cmdqelmt); } } /* end of while */ } #endif /* RTMP_MAC_USB // */