/***************************************** * H2C Msg format : * 0x1DF - 0x1D0 *| 31 - 8 | 7-5 4 - 0 | *| h2c_msg |Class_ID CMD_ID | * * Extend 0x1FF - 0x1F0 *|31 - 0 | *|ext_msg| ******************************************/ static s32 FillH2CCmd_88E(PADAPTER padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer) { struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); u8 h2c_box_num; u32 msgbox_addr; u32 msgbox_ex_addr; u8 cmd_idx,ext_cmd_len; u32 h2c_cmd = 0; u32 h2c_cmd_ex = 0; s32 ret = _FAIL; _func_enter_; padapter = GET_PRIMARY_ADAPTER(padapter); pHalData = GET_HAL_DATA(padapter); if(padapter->bFWReady == _FALSE) { DBG_8192C("FillH2CCmd_88E(): return H2C cmd because fw is not ready\n"); return ret; } _enter_critical_mutex(&(dvobj->h2c_fwcmd_mutex), NULL); if (!pCmdBuffer) { goto exit; } if (CmdLen > RTL88E_MAX_CMD_LEN) { goto exit; } if (padapter->bSurpriseRemoved == _TRUE) goto exit; //pay attention to if race condition happened in H2C cmd setting. do{ h2c_box_num = pHalData->LastHMEBoxNum; if(!_is_fw_read_cmd_down(padapter, h2c_box_num)){ DBG_8192C(" fw read cmd failed...\n"); goto exit; } *(u8*)(&h2c_cmd) = ElementID; if(CmdLen<=3) { _rtw_memcpy((u8*)(&h2c_cmd)+1, pCmdBuffer, CmdLen ); } else{ _rtw_memcpy((u8*)(&h2c_cmd)+1, pCmdBuffer,3); ext_cmd_len = CmdLen-3; _rtw_memcpy((u8*)(&h2c_cmd_ex), pCmdBuffer+3,ext_cmd_len ); //Write Ext command msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num *RTL88E_EX_MESSAGE_BOX_SIZE); #ifdef CONFIG_H2C_EF for(cmd_idx=0;cmd_idx<ext_cmd_len;cmd_idx++ ){ rtw_write8(padapter,msgbox_ex_addr+cmd_idx,*((u8*)(&h2c_cmd_ex)+cmd_idx)); } #else h2c_cmd_ex = le32_to_cpu( h2c_cmd_ex ); rtw_write32(padapter, msgbox_ex_addr, h2c_cmd_ex); #endif } // Write command msgbox_addr =REG_HMEBOX_0 + (h2c_box_num *RTL88E_MESSAGE_BOX_SIZE); #ifdef CONFIG_H2C_EF for(cmd_idx=0;cmd_idx<RTL88E_MESSAGE_BOX_SIZE;cmd_idx++ ){ rtw_write8(padapter,msgbox_addr+cmd_idx,*((u8*)(&h2c_cmd)+cmd_idx)); } #else h2c_cmd = le32_to_cpu( h2c_cmd ); rtw_write32(padapter,msgbox_addr, h2c_cmd); #endif // DBG_8192C("MSG_BOX:%d,CmdLen(%d), reg:0x%x =>h2c_cmd:0x%x, reg:0x%x =>h2c_cmd_ex:0x%x ..\n" // ,pHalData->LastHMEBoxNum ,CmdLen,msgbox_addr,h2c_cmd,msgbox_ex_addr,h2c_cmd_ex); pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL88E_MAX_H2C_BOX_NUMS; }while(0); ret = _SUCCESS; exit: _exit_critical_mutex(&(dvobj->h2c_fwcmd_mutex), NULL); _func_exit_; return ret; }
int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u8 request, u16 value, u16 index, void *pdata, u16 len, u8 requesttype) { _adapter *padapter = pintfhdl->padapter; struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(pdvobjpriv); struct usb_device *udev=pdvobjpriv->pusbdev; unsigned int pipe; int status = 0; u32 tmp_buflen=0; u8 reqtype; u8 *pIo_buf; int vendorreq_times = 0; #ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE u8 *tmp_buf; #else // use stack memory u8 tmp_buf[MAX_USB_IO_CTL_SIZE]; #endif #ifdef CONFIG_CONCURRENT_MODE if(padapter->adapter_type > PRIMARY_ADAPTER) { padapter = padapter->pbuddy_adapter; pdvobjpriv = adapter_to_dvobj(padapter); udev = pdvobjpriv->pusbdev; } #endif //DBG_871X("%s %s:%d\n",__FUNCTION__, current->comm, current->pid); if (RTW_CANNOT_IO(padapter)){ RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usbctrl_vendorreq:(RTW_CANNOT_IO)!!!\n")); status = -EPERM; goto exit; } if(len>MAX_VENDOR_REQ_CMD_SIZE){ DBG_8192C( "[%s] Buffer len error ,vendor request failed\n", __FUNCTION__ ); status = -EINVAL; goto exit; } #ifdef CONFIG_USB_VENDOR_REQ_MUTEX _enter_critical_mutex(&pdvobjpriv->usb_vendor_req_mutex, NULL); #endif // Acquire IO memory for vendorreq #ifdef CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC pIo_buf = pdvobjpriv->usb_vendor_req_buf; #else #ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE tmp_buf = rtw_malloc( (u32) len + ALIGNMENT_UNIT); tmp_buflen = (u32)len + ALIGNMENT_UNIT; #else // use stack memory tmp_buflen = MAX_USB_IO_CTL_SIZE; #endif // Added by Albert 2010/02/09 // For mstar platform, mstar suggests the address for USB IO should be 16 bytes alignment. // Trying to fix it here. pIo_buf = (tmp_buf==NULL)?NULL:tmp_buf + ALIGNMENT_UNIT -((SIZE_PTR)(tmp_buf) & 0x0f ); #endif if ( pIo_buf== NULL) { DBG_8192C( "[%s] pIo_buf == NULL \n", __FUNCTION__ ); status = -ENOMEM; goto release_mutex; } while(++vendorreq_times<= MAX_USBCTRL_VENDORREQ_TIMES) { _rtw_memset(pIo_buf, 0, len); if (requesttype == 0x01) { pipe = usb_rcvctrlpipe(udev, 0);//read_in reqtype = REALTEK_USB_VENQT_READ; } else { pipe = usb_sndctrlpipe(udev, 0);//write_out reqtype = REALTEK_USB_VENQT_WRITE; _rtw_memcpy( pIo_buf, pdata, len); } status = rtw_usb_control_msg(udev, pipe, request, reqtype, value, index, pIo_buf, len, RTW_USB_CONTROL_MSG_TIMEOUT); if ( status == len) // Success this control transfer. { rtw_reset_continual_io_error(pdvobjpriv); if ( requesttype == 0x01 ) { // For Control read transfer, we have to copy the read data from pIo_buf to pdata. _rtw_memcpy( pdata, pIo_buf, len ); } } else { // error cases DBG_8192C("reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d\n" , value,(requesttype == 0x01)?"read":"write" , len, status, *(u32*)pdata, vendorreq_times); if (status < 0) { if(status == (-ESHUTDOWN) || status == -ENODEV ) { padapter->bSurpriseRemoved = _TRUE; } else { #ifdef DBG_CONFIG_ERROR_DETECT { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); pHalData->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL; } #endif } } else // status != len && status >= 0 { if(status > 0) { if ( requesttype == 0x01 ) { // For Control read transfer, we have to copy the read data from pIo_buf to pdata. _rtw_memcpy( pdata, pIo_buf, len ); } } } if(rtw_inc_and_chk_continual_io_error(pdvobjpriv) == _TRUE ){ padapter->bSurpriseRemoved = _TRUE; break; } } // firmware download is checksumed, don't retry if( (value >= FW_START_ADDRESS ) || status == len ) break; } // release IO memory used by vendorreq #ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE rtw_mfree(tmp_buf, tmp_buflen); #endif release_mutex: #ifdef CONFIG_USB_VENDOR_REQ_MUTEX _exit_critical_mutex(&pdvobjpriv->usb_vendor_req_mutex, NULL); #endif exit: return status; }
/***************************************** * H2C Msg format : *| 31 - 8 |7 | 6 - 0 | *| h2c_msg |Ext_bit |CMD_ID | * ******************************************/ static void _FillH2CCmd92D(_adapter* padapter, u8 ElementID, u32 CmdLen, u8* pCmdBuffer) { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); u8 BoxNum; u16 BOXReg=0, BOXExtReg=0; u8 BoxContent[4], BoxExtContent[2]; u8 BufIndex=0; u8 U1btmp; //Read 0x1bf u8 bWriteSucess = _FALSE; u8 IsFwRead = _FALSE; u8 WaitH2cLimmit = 100; u8 WaitWriteH2cLimmit = 100; u8 idx=0; _func_enter_; padapter = GET_PRIMARY_ADAPTER(padapter); pHalData = GET_HAL_DATA(padapter); _enter_critical_mutex(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex), NULL); //DBG_8192C("FillH2CCmd : ElementID=%d \n",ElementID); while(!bWriteSucess) { WaitWriteH2cLimmit--; if(WaitWriteH2cLimmit == 0) { DBG_8192C("FillH2CCmd92C():Write H2C fail because no trigger for FW INT!!!!!!!!\n"); break; } // 2. Find the last BOX number which has been writen. BoxNum = pHalData->LastHMEBoxNum; switch(BoxNum) { case 0: BOXReg = REG_HMEBOX_0; BOXExtReg = REG_HMEBOX_EXT_0; break; case 1: BOXReg = REG_HMEBOX_1; BOXExtReg = REG_HMEBOX_EXT_1; break; case 2: BOXReg = REG_HMEBOX_2; BOXExtReg = REG_HMEBOX_EXT_2; break; case 3: BOXReg = REG_HMEBOX_3; BOXExtReg = REG_HMEBOX_EXT_3; break; default: break; } // 3. Check if the box content is empty. IsFwRead = CheckFwReadLastH2C(padapter, BoxNum); while(!IsFwRead) { //wait until Fw read WaitH2cLimmit--; if(WaitH2cLimmit == 0) { DBG_8192C("FillH2CCmd92C(): Wating too long for FW read clear HMEBox(%d)!!!\n", BoxNum); break; } rtw_udelay_os(10); //us IsFwRead = CheckFwReadLastH2C(padapter, BoxNum); U1btmp = rtw_read8(padapter, 0x1BF); //DBG_8192C("FillH2CCmd92C(): Wating for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n", BoxNum, U1btmp); } // If Fw has not read the last H2C cmd, break and give up this H2C. if(!IsFwRead) { DBG_8192C("FillH2CCmd92C(): Write H2C register BOX[%d] fail!!!!! Fw do not read. \n", BoxNum); break; } // 4. Fill the H2C cmd into box _rtw_memset(BoxContent, 0, sizeof(BoxContent)); _rtw_memset(BoxExtContent, 0, sizeof(BoxExtContent)); BoxContent[0] = ElementID; // Fill element ID //DBG_8192C("FillH2CCmd92C():Write ElementID BOXReg(%4x) = %2x \n", BOXReg, ElementID); switch(CmdLen) { case 1: { BoxContent[0] &= ~(BIT7); _rtw_memcpy((u8 *)(BoxContent)+1, pCmdBuffer+BufIndex, 1); //PlatformEFIOWrite4Byte(Adapter, BOXReg, *((pu4Byte)BoxContent)); //For Endian Free. for(idx= 0; idx < 4; idx++) { rtw_write8(padapter, BOXReg+idx, BoxContent[idx]); } break; } case 2: { BoxContent[0] &= ~(BIT7); _rtw_memcpy((u8 *)(BoxContent)+1, pCmdBuffer+BufIndex, 2); //PlatformEFIOWrite4Byte(Adapter, BOXReg, *((pu4Byte)BoxContent)); for(idx=0; idx < 4; idx++) { rtw_write8(padapter, BOXReg+idx, BoxContent[idx]); } break; } case 3: { BoxContent[0] &= ~(BIT7); _rtw_memcpy((u8 *)(BoxContent)+1, pCmdBuffer+BufIndex, 3); //PlatformEFIOWrite4Byte(Adapter, BOXReg, *((pu4Byte)BoxContent)); for(idx = 0; idx < 4 ; idx++) { rtw_write8(padapter, BOXReg+idx, BoxContent[idx]); } break; } case 4: { BoxContent[0] |= (BIT7); _rtw_memcpy((u8 *)(BoxExtContent), pCmdBuffer+BufIndex, 2); _rtw_memcpy((u8 *)(BoxContent)+1, pCmdBuffer+BufIndex+2, 2); //PlatformEFIOWrite2Byte(Adapter, BOXExtReg, *((pu2Byte)BoxExtContent)); //PlatformEFIOWrite4Byte(Adapter, BOXReg, *((pu4Byte)BoxContent)); for(idx = 0 ; idx < 2 ; idx ++) { rtw_write8(padapter, BOXExtReg+idx, BoxExtContent[idx]); } for(idx = 0 ; idx < 4 ; idx ++) { rtw_write8(padapter, BOXReg+idx, BoxContent[idx]); } break; } case 5: { BoxContent[0] |= (BIT7); _rtw_memcpy((u8 *)(BoxExtContent), pCmdBuffer+BufIndex, 2); _rtw_memcpy((u8 *)(BoxContent)+1, pCmdBuffer+BufIndex+2, 3); //PlatformEFIOWrite2Byte(Adapter, BOXExtReg, *((pu2Byte)BoxExtContent)); //PlatformEFIOWrite4Byte(Adapter, BOXReg, *((pu4Byte)BoxContent)); for(idx = 0 ; idx < 2 ; idx ++) { rtw_write8(padapter, BOXExtReg+idx, BoxExtContent[idx]); } for(idx = 0 ; idx < 4 ; idx ++) { rtw_write8(padapter, BOXReg+idx, BoxContent[idx]); } break; } default: break; } //DBG_8192C("FillH2CCmd(): BoxExtContent=0x%04x\n", *(u16*)BoxExtContent); //DBG_8192C("FillH2CCmd(): BoxContent=0x%08x\n", *(u32*)BoxContent); // 5. Normal chip does not need to check if the H2C cmd has be written successfully. // 92D test chip does not need to check, bWriteSucess = _TRUE; // Record the next BoxNum pHalData->LastHMEBoxNum = BoxNum+1; if(pHalData->LastHMEBoxNum == 4) // loop to 0 pHalData->LastHMEBoxNum = 0; //DBG_8192C("FillH2CCmd92C():pHalData->LastHMEBoxNum = %d\n", pHalData->LastHMEBoxNum); } _exit_critical_mutex(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex), NULL); _func_exit_; }