SAMA5D4 Xplained Ultra Board BSP
guowenxue
2019-08-19 2e7235d10c6dbff81960282e1a1e2e798f9b8db8
Add mt7601u-sta and rtl8188eus driver in drivers
608 files added
531198 ■■■■■ changed files
linux-bsp/drivers/mt7601u-sta/Kbuild 10 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/Makefile 10 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/README.md 64 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/core.c 78 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/debugfs.c 172 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/dma.c 529 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/dma.h 127 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/eeprom.c 418 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/eeprom.h 151 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/init.c 639 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/initvals.h 164 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/initvals_phy.h 291 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/mac.c 581 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/mac.h 178 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/main.c 432 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/mcu.c 536 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/mcu.h 94 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/mt7601u.h 396 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/phy.c 1251 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/regs.h 639 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/trace.c 21 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/trace.h 400 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/tx.c 322 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/usb.c 362 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/usb.h 79 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/util.c 42 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/util.h 77 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/Kconfig 6 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/LICENSE 12 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/Makefile 1957 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/README.md 61 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/efuse/rtw_efuse.c 2949 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_ap.c 4171 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_beamforming.c 3157 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_br_ext.c 1585 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_bt_mp.c 1580 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_btcoex.c 1717 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_btcoex_wifionly.c 42 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_cmd.c 4803 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_debug.c 5215 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_eeprom.c 374 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_ieee80211.c 2736 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_io.c 701 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_ioctl_query.c 171 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_ioctl_rtl.c 904 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_ioctl_set.c 1254 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_iol.c 387 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_mem.c 114 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_mi.c 1286 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_mlme.c 4669 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_mlme_ext.c 15724 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_mp.c 3569 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_mp_ioctl.c 2534 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_odm.c 446 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_p2p.c 5310 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_pwrctrl.c 2528 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_recv.c 4724 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_rf.c 1164 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_sdio.c 98 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_security.c 3197 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_sreset.c 346 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_sta_mgt.c 1187 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_tdls.c 3332 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_vht.c 803 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_wapi.c 1240 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_wapi_sms4.c 908 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_wlan_util.c 4656 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/core/rtw_xmit.c 5545 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/HalPwrSeqCmd.c 161 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.c 2053 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.h 144 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.c 2058 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.h 165 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.c 3281 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.h 209 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.c 4398 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.h 201 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.c 1598 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.h 171 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.c 3780 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.h 179 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.c 3669 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.h 211 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.c 4155 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.h 186 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.c 2973 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.h 201 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.c 4826 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.h 213 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.c 3223 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.h 210 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.c 4222 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.h 180 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtcOutSrc.h 681 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/Mp_Precomp.h 56 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/HalPhyRf.c 530 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/HalPhyRf.h 89 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/PhyDM_Adaptivity.c 873 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/PhyDM_Adaptivity.h 157 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm.c 14017 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm.h 2409 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_AntDiv.c 2269 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_AntDiv.h 136 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_HWConfig.c 2363 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_HWConfig.h 237 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_RegDefine11AC.h 81 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_RegDefine11N.h 187 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_debug.c 629 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_debug.h 898 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_interface.c 751 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_interface.h 394 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_precomp.h 307 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_reg.h 122 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_types.h 282 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/Hal8188ERateAdaptive.c 1250 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/Hal8188ERateAdaptive.h 108 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/Hal8188EReg.h 54 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_BB.c 1652 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_BB.h 74 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_FW.c 5010 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_FW.h 83 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_MAC.c 608 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_MAC.h 47 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_RF.c 1404 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_RF.h 83 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalPhyRf_8188e.c 3299 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalPhyRf_8188e.h 141 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/odm_RTL8188E.c 459 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/odm_RTL8188E.h 64 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/odm_RegConfig8188E.c 234 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/odm_RegConfig8188E.h 96 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8192e1ant.c 3417 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8192e1ant.h 226 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8192e2ant.c 4377 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8192e2ant.h 211 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8703b1ant.c 4293 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8703b1ant.h 404 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723b1ant.c 5113 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723b1ant.h 293 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723b2ant.c 4958 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723b2ant.h 217 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723bwifionly.c 68 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723bwifionly.h 8 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723d1ant.c 6225 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723d1ant.h 413 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723d2ant.c 6774 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723d2ant.h 418 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8812a1ant.c 3461 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8812a1ant.h 230 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8812a2ant.c 5624 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8812a2ant.h 227 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821a1ant.c 3289 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821a1ant.h 214 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821a2ant.c 4637 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821a2ant.h 211 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821c1ant.c 6674 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821c1ant.h 473 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821c2ant.c 6936 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821c2ant.h 478 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821cwifionly.c 186 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821cwifionly.h 70 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8822b1ant.c 6840 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8822b1ant.h 433 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8822b2ant.c 5543 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8822b2ant.h 493 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8822bwifionly.c 54 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8822bwifionly.h 22 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/halbtcoutsrc.h 1003 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/btc/mp_precomp.h 90 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/efuse/efuse_mask.h 106 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/efuse/rtl8188e/HalEfuseMask8188E_PCIE.c 101 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/efuse/rtl8188e/HalEfuseMask8188E_PCIE.h 39 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/efuse/rtl8188e/HalEfuseMask8188E_SDIO.c 101 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/efuse/rtl8188e/HalEfuseMask8188E_SDIO.h 39 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/efuse/rtl8188e/HalEfuseMask8188E_USB.c 100 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/efuse/rtl8188e/HalEfuseMask8188E_USB.h 39 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/hal_btcoex.c 4474 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/hal_btcoex_wifionly.c 156 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/hal_com.c 11422 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/hal_com_c2h.h 119 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/hal_com_phycfg.c 5452 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/hal_dm.c 224 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/hal_dm.h 25 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/hal_halmac.c 2635 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/hal_halmac.h 121 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/hal_hci/hal_usb.c 529 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/hal_intf.c 1416 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/hal_mcc.c 1877 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/hal_mp.c 2212 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/hal_phy.c 260 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/led/hal_usb_led.c 4287 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/halhwimg.h 123 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/halphyrf_ap.c 2665 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/halphyrf_ap.h 178 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/halphyrf_ce.c 799 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/halphyrf_ce.h 117 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/halphyrf_win.c 784 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/halphyrf_win.h 119 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/mp_precomp.h 19 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm.c 3425 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm.h 1336 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_acs.c 1154 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_acs.h 105 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_adaptivity.c 1130 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_adaptivity.h 219 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_adc_sampling.c 764 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_adc_sampling.h 147 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_antdect.c 864 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_antdect.h 95 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_antdiv.c 5234 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_antdiv.h 632 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_beamforming.c 1880 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_beamforming.h 374 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_ccx.c 392 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_ccx.h 102 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_cfotracking.c 360 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_cfotracking.h 69 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_debug.c 3061 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_debug.h 359 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dfs.c 257 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dfs.h 75 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dig.c 2142 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dig.h 368 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dynamic_rx_path.c 357 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dynamic_rx_path.h 137 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dynamicbbpowersaving.c 111 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dynamicbbpowersaving.h 57 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dynamictxpower.c 535 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dynamictxpower.h 110 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_edcaturbocheck.c 698 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_edcaturbocheck.h 102 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_features.h 189 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_hwconfig.c 3628 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_hwconfig.h 574 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_interface.c 1005 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_interface.h 416 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_iqk.h 65 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_kfree.c 190 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_kfree.h 45 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_noisemonitor.c 292 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_noisemonitor.h 47 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_pathdiv.c 696 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_pathdiv.h 319 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_powertracking_ap.c 1205 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_powertracking_ap.h 351 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_powertracking_ce.c 745 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_powertracking_ce.h 334 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_powertracking_win.c 776 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_powertracking_win.h 299 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_pre_define.h 677 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_precomp.h 351 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_rainfo.c 3429 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_rainfo.h 585 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_reg.h 214 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_regdefine11ac.h 93 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_regdefine11n.h 212 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_types.h 292 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtchnlplan.c 475 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtchnlplan.h 682 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/hal8188erateadaptive.c 1417 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/hal8188erateadaptive.h 110 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/hal8188ereg.h 64 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_bb.c 1764 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_bb.h 58 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_mac.c 288 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_mac.h 38 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_rf.c 2370 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_rf.h 128 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_s_fw.c 3647 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_s_fw.h 61 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_t_fw.c 3901 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_t_fw.h 72 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halphyrf_8188e_ap.c 2996 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halphyrf_8188e_ap.h 135 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halphyrf_8188e_ce.c 3150 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halphyrf_8188e_ce.h 142 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halphyrf_8188e_win.c 3189 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halphyrf_8188e_win.h 143 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/phydm_regconfig8188e.c 219 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/phydm_regconfig8188e.h 95 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/phydm_rtl8188e.c 388 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/phydm_rtl8188e.h 78 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/version_rtl8188e.h 10 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/halcomtxbf.c 538 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/halcomtxbf.h 179 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbf8192e.c 391 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbf8192e.h 60 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbf8814a.c 700 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbf8814a.h 89 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbf8822b.c 1099 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbf8822b.h 79 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbfinterface.c 1502 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbfinterface.h 165 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbfjaguar.c 526 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbfjaguar.h 74 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/phydm_hal_txbf_api.c 179 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/phydm_hal_txbf_api.h 69 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/Hal8188EPwrSeq.c 87 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/hal8188e_s_fw.c 7303 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/hal8188e_s_fw.h 45 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/hal8188e_t_fw.c 7749 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/hal8188e_t_fw.h 43 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_cmd.c 825 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_dm.c 434 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_hal_init.c 4867 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_mp.c 1153 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_phycfg.c 2021 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_rf6052.c 325 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_rxdesc.c 94 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_sreset.c 121 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_xmit.c 306 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/usb/rtl8188eu_led.c 160 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/usb/rtl8188eu_recv.c 33 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/usb/rtl8188eu_xmit.c 1297 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/usb/usb_halinit.c 2610 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/hal/rtl8188e/usb/usb_ops_linux.c 293 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8188EPhyCfg.h 265 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8188EPhyReg.h 1105 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8188EPwrSeq.h 175 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8188FPhyCfg.h 139 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8188FPhyReg.h 1170 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8188FPwrSeq.h 198 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8192CPhyCfg.h 241 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8192CPhyReg.h 1132 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8192DPhyCfg.h 293 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8192DPhyReg.h 1167 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8192EPhyCfg.h 153 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8192EPhyReg.h 1132 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8192EPwrSeq.h 155 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8703BPhyCfg.h 137 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8703BPhyReg.h 1138 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8703BPwrSeq.h 184 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8723APhyCfg.h 39 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8723APhyReg.h 74 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8723BPhyCfg.h 137 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8723BPhyReg.h 1136 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8723BPwrSeq.h 232 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8723DPhyCfg.h 136 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8723DPhyReg.h 1139 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8723DPwrSeq.h 193 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8723PwrSeq.h 169 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8812PhyCfg.h 148 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8812PhyReg.h 738 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8812PwrSeq.h 209 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8814PhyCfg.h 269 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8814PhyReg.h 866 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8814PwrSeq.h 236 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/Hal8821APwrSeq.h 186 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/HalPwrSeqCmd.h 135 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/HalVerDef.h 199 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/autoconf.h 361 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/basic_types.h 384 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/byteorder/big_endian.h 87 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/byteorder/generic.h 212 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/byteorder/little_endian.h 89 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/byteorder/swab.h 141 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/byteorder/swabb.h 156 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/circ_buf.h 28 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/cmd_osdep.h 31 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/custom_gpio.h 32 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/drv_conf.h 313 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/drv_types.h 1593 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/drv_types_ce.h 91 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/drv_types_gspi.h 54 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/drv_types_linux.h 24 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/drv_types_pci.h 271 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/drv_types_sdio.h 91 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/drv_types_xp.h 93 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/ethernet.h 41 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/gspi_hal.h 35 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/gspi_ops.h 185 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/gspi_ops_linux.h 23 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/gspi_osintf.h 30 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/h2clbk.h 31 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_btcoex.h 93 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_btcoex_wifionly.h 47 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_com.h 685 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_com_h2c.h 551 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_com_led.h 396 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_com_phycfg.h 348 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_com_reg.h 1823 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_data.h 1050 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_gspi.h 31 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_ic_cfg.h 205 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_intf.h 775 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_pg.h 801 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_phy.h 243 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_phy_reg.h 30 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/hal_sdio.h 36 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/ieee80211.h 1935 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/ieee80211_ext.h 476 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/if_ether.h 111 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/ioctl_cfg80211.h 179 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/ip.h 140 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/linux/wireless.h 92 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/mlme_osdep.h 36 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/mp_custom_oid.h 353 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/nic_spec.h 46 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/osdep_intf.h 171 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/osdep_service.h 703 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/osdep_service_bsd.h 749 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/osdep_service_ce.h 192 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/osdep_service_linux.h 476 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/osdep_service_xp.h 202 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/pci_hal.h 53 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/pci_ops.h 96 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/pci_osintf.h 43 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/recv_osdep.h 68 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188e_cmd.h 179 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188e_dm.h 32 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188e_hal.h 320 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188e_led.h 40 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188e_recv.h 166 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188e_rf.h 32 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188e_spec.h 152 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188e_sreset.h 29 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188e_xmit.h 300 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188f_cmd.h 219 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188f_dm.h 47 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188f_hal.h 271 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188f_led.h 48 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188f_recv.h 73 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188f_rf.h 30 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188f_spec.h 291 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188f_sreset.h 29 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8188f_xmit.h 338 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192c_cmd.h 99 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192c_dm.h 104 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192c_event.h 28 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192c_hal.h 415 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192c_led.h 37 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192c_recv.h 106 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192c_rf.h 45 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192c_spec.h 143 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192c_sreset.h 30 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192c_xmit.h 166 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192d_cmd.h 97 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192d_dm.h 50 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192d_hal.h 409 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192d_led.h 38 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192d_recv.h 103 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192d_rf.h 50 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192d_spec.h 115 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192d_xmit.h 184 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192e_cmd.h 161 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192e_dm.h 33 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192e_hal.h 332 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192e_led.h 40 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192e_recv.h 173 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192e_rf.h 33 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192e_spec.h 317 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192e_sreset.h 29 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8192e_xmit.h 451 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8703b_cmd.h 218 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8703b_dm.h 47 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8703b_hal.h 277 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8703b_led.h 48 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8703b_recv.h 91 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8703b_rf.h 30 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8703b_spec.h 468 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8703b_sreset.h 29 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8703b_xmit.h 338 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723a_cmd.h 215 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723a_dm.h 46 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723a_hal.h 467 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723a_led.h 45 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723a_pg.h 24 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723a_recv.h 41 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723a_rf.h 27 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723a_spec.h 103 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723a_sreset.h 30 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723a_xmit.h 237 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723b_cmd.h 218 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723b_dm.h 47 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723b_hal.h 283 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723b_led.h 48 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723b_recv.h 91 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723b_rf.h 30 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723b_spec.h 284 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723b_sreset.h 29 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723b_xmit.h 338 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723d_cmd.h 211 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723d_dm.h 47 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723d_hal.h 316 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723d_led.h 48 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723d_lps_poff.h 61 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723d_recv.h 120 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723d_rf.h 26 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723d_spec.h 445 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723d_sreset.h 29 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8723d_xmit.h 522 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8812a_cmd.h 171 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8812a_dm.h 32 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8812a_hal.h 361 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8812a_led.h 41 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8812a_recv.h 158 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8812a_rf.h 33 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8812a_spec.h 264 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8812a_sreset.h 29 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8812a_xmit.h 371 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8814a_cmd.h 170 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8814a_dm.h 28 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8814a_hal.h 324 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8814a_led.h 40 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8814a_recv.h 191 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8814a_rf.h 33 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8814a_spec.h 643 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8814a_sreset.h 29 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8814a_xmit.h 310 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8821a_spec.h 96 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8821a_xmit.h 178 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8821c_dm.h 30 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8821c_hal.h 86 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8821c_spec.h 195 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8821ce_hal.h 28 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8821cs_hal.h 28 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8821cu_hal.h 29 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8822b_hal.h 218 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8822be_hal.h 30 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8822bs_hal.h 32 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtl8822bu_hal.h 63 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_android.h 115 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_ap.h 88 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_beamforming.h 390 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_br_ext.h 74 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_bt_mp.h 293 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_btcoex.h 444 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_btcoex_wifionly.h 27 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_byteorder.h 38 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_cmd.h 1320 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_debug.h 650 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_eeprom.h 121 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_efuse.h 245 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_event.h 135 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_ht.h 219 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_io.h 576 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_ioctl.h 323 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_ioctl_query.h 30 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_ioctl_rtl.h 80 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_ioctl_set.h 75 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_iol.h 136 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_mcc.h 220 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_mem.h 41 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_mi.h 240 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_mlme.h 1205 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_mlme_ext.h 1290 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_mp.h 946 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_mp_ioctl.h 575 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_mp_phy_regdef.h 1099 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_odm.h 55 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_p2p.h 176 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_pwrctrl.h 559 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_qos.h 34 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_recv.h 898 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_rf.h 293 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_sdio.h 30 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_security.h 494 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_sreset.h 60 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_tdls.h 173 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_version.h 1 ●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_vht.h 144 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_wapi.h 214 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_wifi_regd.h 25 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/rtw_xmit.h 991 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/sdio_hal.h 54 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/sdio_ops.h 161 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/sdio_ops_ce.h 54 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/sdio_ops_linux.h 53 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/sdio_ops_xp.h 54 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/sdio_osintf.h 30 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/sta_info.h 671 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/usb_hal.h 67 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/usb_ops.h 133 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/usb_ops_linux.h 103 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/usb_osintf.h 31 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/usb_vendor_req.h 61 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/wifi.h 1399 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/wlan_bssdef.h 690 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/include/xmit_osdep.h 99 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/custom_gpio_linux.c 346 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/ioctl_cfg80211.c 7281 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/ioctl_cfg80211.h 323 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/ioctl_linux.c 13390 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/ioctl_mp.c 2412 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/mlme_linux.c 604 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/os_intfs.c 4489 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/recv_linux.c 885 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/rtw_android.c 1278 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/rtw_cfgvendor.c 1328 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/rtw_cfgvendor.h 245 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/rtw_proc.c 3216 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/rtw_proc.h 65 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/usb_intf.c 1647 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/usb_ops_linux.c 1105 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/wifi_regd.c 549 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/linux/xmit_linux.c 535 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/os_dep/osdep_service.c 2769 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/platform/custom_country_chplan.h 28 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/platform/platform_ARM_SUN50IW1P1_sdio.c 91 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/platform/platform_ARM_SUNnI_sdio.c 135 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/platform/platform_ARM_SUNxI_sdio.c 95 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/platform/platform_ARM_SUNxI_usb.c 141 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/platform/platform_ARM_WMT_sdio.c 51 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/platform/platform_RTK_DMP_usb.c 35 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/platform/platform_arm_act_sdio.c 58 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/platform/platform_ops.c 37 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/platform/platform_ops.h 31 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/rtl8188eus/platform/platform_sprd_sdio.c 89 ●●●●● patch | view | raw | blame | history
linux-bsp/drivers/mt7601u-sta/Kbuild
New file
@@ -0,0 +1,10 @@
EXTRA_CFLAGS += -Werror -Wenum-compare
ccflags-y += -D__CHECK_ENDIAN__
obj-m := mt7601u.o
mt7601u-y := \
    usb.o init.o main.o mcu.o trace.o dma.o core.o eeprom.o phy.o \
    mac.o util.o debugfs.o tx.o
CFLAGS_trace.o := -I$(src)
linux-bsp/drivers/mt7601u-sta/Makefile
New file
@@ -0,0 +1,10 @@
KDIR ?= ../../linux-at91/
CROSS_COMPILE=/opt/buildroot/cortex-a5/bin/arm-linux-
default:
    $(MAKE) -C $(KDIR) M=$$PWD
clean:
    $(MAKE) -C $(KDIR) M=$$PWD clean
install:
    $(MAKE) -C $(KDIR) M=$$PWD modules_install
linux-bsp/drivers/mt7601u-sta/README.md
New file
@@ -0,0 +1,64 @@
### Download:
Download from:  https://github.com/kuba-moo/mt7601u.git
MT7601 driver builtin linux kernel since version v4.2, the kernel under the version need this driver. And it's just only server for wpa_supplicant but not hostapd
### ChangeLog:
1, Updata Makefile to support SAMA5D4 build
This is a Linux driver for MediaTek MT7601U USB dongle. It was written from scratch based on the vendor GPL-driver. Unlike the vendor driver this driver uses modern Linux WiFi infrastructure and should work flawlessly with NetworkManager, wicd, wpa_supplicant and such. This driver was merged into mainline and is part of official Linux kernel since version v4.2. If you are using Linux 4.2 or later there is no need to install this driver.
### Building and using
To use this driver you need to upgrade your kernel to at least **Linux 3.19**. You also have to grab a copy of the firmware from the vendor driver. Download the vendor driver (see section below) and copy file *MT7601U.bin* to */lib/firmware*:
```sh
# cd where-you-put-the-vendor-driver
# cp src/mcu/bin/MT7601.bin /lib/firmware/mt7601u.bin
```
Note that name of the file in */lib/firmware* is in lowercase.
After that **make sure you have installed all packages required by your distro to build kernel modules** (```apt-get install linux-headers-$(uname -r)``` or ```yum install kernel-devel``` etc). Build the driver and load it:
```sh
$ git clone https://github.com/kuba-moo/mt7601u.git
$ cd mt7601u
$ make
# modprobe mac80211
# insmod ./mt7601u.ko
```
Now when you connect your device a new network interface should be created. Something like this should appear in your kernel logs:
```
[ 5515.098424] mt7601u 1-6:1.0: ASIC revision: 76010001  MAC revision: 76010500
[ 5515.100954] mt7601u 1-6:1.0: Firmware Version: 0.1.00 Build: 7640 Build time: 201302052146____
[ 5515.466817] mt7601u 1-6:1.0: Warning: unsupported EEPROM version 0d
[ 5515.466876] mt7601u 1-6:1.0: EEPROM ver:0d fae:00
[ 5515.467561] mt7601u 1-6:1.0: EEPROM country region 01 (channels 1-13)
[ 5515.713155] ieee80211 phy26: Selected rate control algorithm 'minstrel_ht'
[ 5515.718977] usbcore: registered new interface driver mt7601u
```
The warning about EEPROM version is harmless but keep an eye on the logs and if you spot any errors please report them here.
If you want the driver to load automatically you can do the following:
```
$ make && sudo make install && depmod
```
However, please remember that this installs the driver *only for your current kernel* and you will have to redo this every time your kernel is updated!
### Supported hardware
The driver was tested for devices with USB ID of 148f:7601. Specifically I tested it with:
 * TP-LINK TL-WN727N v4;
 * Xiaomi Mini USB;
 * the no-name black&red device from ebay with small detachable antenna.
Also tested with USB ID of 148f:760b wich has MT7601UM chip and works fine with this driver.
But in principle it *should* work with any device supported by the vendor driver.
### Vendor driver
The original vendor driver can be downloaded from MediaTek's website (http://www.mediatek.com/en/downloads1/downloads/mt7601u-usb/). However, version 3.0.0.4 is broken on recent kernels so you may want to grab one of the improved versions which people put up on GH (like this one: https://github.com/porjo/mt7601u).
linux-bsp/drivers/mt7601u-sta/core.c
New file
@@ -0,0 +1,78 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#include "mt7601u.h"
int mt7601u_wait_asic_ready(struct mt7601u_dev *dev)
{
    int i = 100;
    u32 val;
    do {
        if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
            return -EIO;
        val = mt7601u_rr(dev, MT_MAC_CSR0);
        if (val && ~val)
            return 0;
        udelay(10);
    } while (i--);
    return -EIO;
}
bool mt76_poll(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val,
           int timeout)
{
    u32 cur;
    timeout /= 10;
    do {
        if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
            return false;
        cur = mt7601u_rr(dev, offset) & mask;
        if (cur == val)
            return true;
        udelay(10);
    } while (timeout-- > 0);
    dev_err(dev->dev, "Error: Time out with reg %08x\n", offset);
    return false;
}
bool mt76_poll_msec(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val,
            int timeout)
{
    u32 cur;
    timeout /= 10;
    do {
        if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
            return false;
        cur = mt7601u_rr(dev, offset) & mask;
        if (cur == val)
            return true;
        msleep(10);
    } while (timeout-- > 0);
    dev_err(dev->dev, "Error: Time out with reg %08x\n", offset);
    return false;
}
linux-bsp/drivers/mt7601u-sta/debugfs.c
New file
@@ -0,0 +1,172 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#include <linux/debugfs.h>
#include "mt7601u.h"
#include "eeprom.h"
static int
mt76_reg_set(void *data, u64 val)
{
    struct mt7601u_dev *dev = data;
    mt76_wr(dev, dev->debugfs_reg, val);
    return 0;
}
static int
mt76_reg_get(void *data, u64 *val)
{
    struct mt7601u_dev *dev = data;
    *val = mt76_rr(dev, dev->debugfs_reg);
    return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(fops_regval, mt76_reg_get, mt76_reg_set, "0x%08llx\n");
static int
mt7601u_ampdu_stat_read(struct seq_file *file, void *data)
{
    struct mt7601u_dev *dev = file->private;
    int i, j;
#define stat_printf(grp, off, name)                    \
    seq_printf(file, #name ":\t%llu\n", dev->stats.grp[off])
    stat_printf(rx_stat, 0, rx_crc_err);
    stat_printf(rx_stat, 1, rx_phy_err);
    stat_printf(rx_stat, 2, rx_false_cca);
    stat_printf(rx_stat, 3, rx_plcp_err);
    stat_printf(rx_stat, 4, rx_fifo_overflow);
    stat_printf(rx_stat, 5, rx_duplicate);
    stat_printf(tx_stat, 0, tx_fail_cnt);
    stat_printf(tx_stat, 1, tx_bcn_cnt);
    stat_printf(tx_stat, 2, tx_success);
    stat_printf(tx_stat, 3, tx_retransmit);
    stat_printf(tx_stat, 4, tx_zero_len);
    stat_printf(tx_stat, 5, tx_underflow);
    stat_printf(aggr_stat, 0, non_aggr_tx);
    stat_printf(aggr_stat, 1, aggr_tx);
    stat_printf(zero_len_del, 0, tx_zero_len_del);
    stat_printf(zero_len_del, 1, rx_zero_len_del);
#undef stat_printf
    seq_puts(file, "Aggregations stats:\n");
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 8; j++)
            seq_printf(file, "%08llx ",
                   dev->stats.aggr_n[i * 8 + j]);
        seq_putc(file, '\n');
    }
    seq_printf(file, "recent average AMPDU len: %d\n",
           atomic_read(&dev->avg_ampdu_len));
    return 0;
}
static int
mt7601u_ampdu_stat_open(struct inode *inode, struct file *f)
{
    return single_open(f, mt7601u_ampdu_stat_read, inode->i_private);
}
static const struct file_operations fops_ampdu_stat = {
    .open = mt7601u_ampdu_stat_open,
    .read = seq_read,
    .llseek = seq_lseek,
    .release = single_release,
};
static int
mt7601u_eeprom_param_read(struct seq_file *file, void *data)
{
    struct mt7601u_dev *dev = file->private;
    struct mt7601u_rate_power *rp = &dev->ee->power_rate_table;
    struct tssi_data *td = &dev->ee->tssi_data;
    int i;
    seq_printf(file, "RF freq offset: %hhx\n", dev->ee->rf_freq_off);
    seq_printf(file, "RSSI offset: %hhx %hhx\n",
           dev->ee->rssi_offset[0], dev->ee->rssi_offset[1]);
    seq_printf(file, "Reference temp: %hhx\n", dev->ee->ref_temp);
    seq_printf(file, "LNA gain: %hhx\n", dev->ee->lna_gain);
    seq_printf(file, "Reg channels: %hhu-%hhu\n", dev->ee->reg.start,
           dev->ee->reg.start + dev->ee->reg.num - 1);
    seq_puts(file, "Per rate power:\n");
    for (i = 0; i < 2; i++)
        seq_printf(file, "\t raw:%02hhx bw20:%02hhx bw40:%02hhx\n",
               rp->cck[i].raw, rp->cck[i].bw20, rp->cck[i].bw40);
    for (i = 0; i < 4; i++)
        seq_printf(file, "\t raw:%02hhx bw20:%02hhx bw40:%02hhx\n",
               rp->ofdm[i].raw, rp->ofdm[i].bw20, rp->ofdm[i].bw40);
    for (i = 0; i < 4; i++)
        seq_printf(file, "\t raw:%02hhx bw20:%02hhx bw40:%02hhx\n",
               rp->ht[i].raw, rp->ht[i].bw20, rp->ht[i].bw40);
    seq_puts(file, "Per channel power:\n");
    for (i = 0; i < 7; i++)
        seq_printf(file, "\t tx_power  ch%u:%02hhx ch%u:%02hhx\n",
               i * 2 + 1, dev->ee->chan_pwr[i * 2],
               i * 2 + 2, dev->ee->chan_pwr[i * 2 + 1]);
    if (!dev->ee->tssi_enabled)
        return 0;
    seq_puts(file, "TSSI:\n");
    seq_printf(file, "\t slope:%02hhx\n", td->slope);
    seq_printf(file, "\t offset=%02hhx %02hhx %02hhx\n",
           td->offset[0], td->offset[1], td->offset[2]);
    seq_printf(file, "\t delta_off:%08x\n", td->tx0_delta_offset);
    return 0;
}
static int
mt7601u_eeprom_param_open(struct inode *inode, struct file *f)
{
    return single_open(f, mt7601u_eeprom_param_read, inode->i_private);
}
static const struct file_operations fops_eeprom_param = {
    .open = mt7601u_eeprom_param_open,
    .read = seq_read,
    .llseek = seq_lseek,
    .release = single_release,
};
void mt7601u_init_debugfs(struct mt7601u_dev *dev)
{
    struct dentry *dir;
    dir = debugfs_create_dir("mt7601u", dev->hw->wiphy->debugfsdir);
    if (!dir)
        return;
    debugfs_create_u8("temperature", S_IRUSR, dir, &dev->raw_temp);
    debugfs_create_u32("temp_mode", S_IRUSR, dir, &dev->temp_mode);
    debugfs_create_u32("regidx", S_IRUSR | S_IWUSR, dir, &dev->debugfs_reg);
    debugfs_create_file("regval", S_IRUSR | S_IWUSR, dir, dev,
                &fops_regval);
    debugfs_create_file("ampdu_stat", S_IRUSR, dir, dev, &fops_ampdu_stat);
    debugfs_create_file("eeprom_param", S_IRUSR, dir, dev,
                &fops_eeprom_param);
}
linux-bsp/drivers/mt7601u-sta/dma.c
New file
@@ -0,0 +1,529 @@
/*
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#include "mt7601u.h"
#include "dma.h"
#include "usb.h"
#include "trace.h"
static int mt7601u_submit_rx_buf(struct mt7601u_dev *dev,
                 struct mt7601u_dma_buf_rx *e, gfp_t gfp);
static unsigned int ieee80211_get_hdrlen_from_buf(const u8 *data, unsigned len)
{
    const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)data;
    unsigned int hdrlen;
    if (unlikely(len < 10))
        return 0;
    hdrlen = ieee80211_hdrlen(hdr->frame_control);
    if (unlikely(hdrlen > len))
        return 0;
    return hdrlen;
}
static struct sk_buff *
mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
            void *data, u32 seg_len, u32 truesize, struct page *p)
{
    struct sk_buff *skb;
    u32 true_len, hdr_len = 0, copy, frag;
    skb = alloc_skb(p ? 128 : seg_len, GFP_ATOMIC);
    if (!skb)
        return NULL;
    true_len = mt76_mac_process_rx(dev, skb, data, rxwi);
    if (!true_len || true_len > seg_len)
        goto bad_frame;
    hdr_len = ieee80211_get_hdrlen_from_buf(data, true_len);
    if (!hdr_len)
        goto bad_frame;
    if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) {
        memcpy(skb_put(skb, hdr_len), data, hdr_len);
        data += hdr_len + 2;
        true_len -= hdr_len;
        hdr_len = 0;
    }
    /* If not doing paged RX allocated skb will always have enough space */
    copy = (true_len <= skb_tailroom(skb)) ? true_len : hdr_len + 8;
    frag = true_len - copy;
    memcpy(skb_put(skb, copy), data, copy);
    data += copy;
    if (frag) {
        skb_add_rx_frag(skb, 0, p, data - page_address(p),
                frag, truesize);
        get_page(p);
    }
    return skb;
bad_frame:
    dev_err(dev->dev, "Error: incorrect frame len:%u hdr:%u\n",
        true_len, hdr_len);
    dev_kfree_skb(skb);
    return NULL;
}
static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data,
                   u32 seg_len, struct page *p)
{
    struct sk_buff *skb;
    struct mt7601u_rxwi *rxwi;
    u32 fce_info, truesize = seg_len;
    /* DMA_INFO field at the beginning of the segment contains only some of
     * the information, we need to read the FCE descriptor from the end.
     */
    fce_info = get_unaligned_le32(data + seg_len - MT_FCE_INFO_LEN);
    seg_len -= MT_FCE_INFO_LEN;
    data += MT_DMA_HDR_LEN;
    seg_len -= MT_DMA_HDR_LEN;
    rxwi = (struct mt7601u_rxwi *) data;
    data += sizeof(struct mt7601u_rxwi);
    seg_len -= sizeof(struct mt7601u_rxwi);
    if (unlikely(rxwi->zero[0] || rxwi->zero[1] || rxwi->zero[2]))
        dev_err_once(dev->dev, "Error: RXWI zero fields are set\n");
    if (unlikely(MT76_GET(MT_RXD_INFO_TYPE, fce_info)))
        dev_err_once(dev->dev, "Error: RX path seen a non-pkt urb\n");
    trace_mt_rx(dev, rxwi, fce_info);
    skb = mt7601u_rx_skb_from_seg(dev, rxwi, data, seg_len, truesize, p);
    if (!skb)
        return;
    spin_lock(&dev->mac_lock);
    ieee80211_rx(dev->hw, skb);
    spin_unlock(&dev->mac_lock);
}
static u16 mt7601u_rx_next_seg_len(u8 *data, u32 data_len)
{
    u32 min_seg_len = MT_DMA_HDR_LEN + MT_RX_INFO_LEN +
        sizeof(struct mt7601u_rxwi) + MT_FCE_INFO_LEN;
    u16 dma_len = get_unaligned_le16(data);
    if (data_len < min_seg_len ||
        WARN_ON(!dma_len) ||
        WARN_ON(dma_len + MT_DMA_HDRS > data_len) ||
        WARN_ON(dma_len & 0x3))
        return 0;
    return MT_DMA_HDRS + dma_len;
}
static void
mt7601u_rx_process_entry(struct mt7601u_dev *dev, struct mt7601u_dma_buf_rx *e)
{
    u32 seg_len, data_len = e->urb->actual_length;
    u8 *data = page_address(e->p);
    struct page *new_p = NULL;
    int cnt = 0;
    if (!test_bit(MT7601U_STATE_INITIALIZED, &dev->state))
        return;
    /* Copy if there is very little data in the buffer. */
    if (data_len > 512)
        new_p = dev_alloc_pages(MT_RX_ORDER);
    while ((seg_len = mt7601u_rx_next_seg_len(data, data_len))) {
        mt7601u_rx_process_seg(dev, data, seg_len, new_p ? e->p : NULL);
        data_len -= seg_len;
        data += seg_len;
        cnt++;
    }
    if (cnt > 1)
        trace_mt_rx_dma_aggr(dev, cnt, !!new_p);
    if (new_p) {
        /* we have one extra ref from the allocator */
        __free_pages(e->p, MT_RX_ORDER);
        e->p = new_p;
    }
}
static struct mt7601u_dma_buf_rx *
mt7601u_rx_get_pending_entry(struct mt7601u_dev *dev)
{
    struct mt7601u_rx_queue *q = &dev->rx_q;
    struct mt7601u_dma_buf_rx *buf = NULL;
    unsigned long flags;
    spin_lock_irqsave(&dev->rx_lock, flags);
    if (!q->pending)
        goto out;
    buf = &q->e[q->start];
    q->pending--;
    q->start = (q->start + 1) % q->entries;
out:
    spin_unlock_irqrestore(&dev->rx_lock, flags);
    return buf;
}
static void mt7601u_complete_rx(struct urb *urb)
{
    struct mt7601u_dev *dev = urb->context;
    struct mt7601u_rx_queue *q = &dev->rx_q;
    unsigned long flags;
    spin_lock_irqsave(&dev->rx_lock, flags);
    if (mt7601u_urb_has_error(urb))
        dev_err(dev->dev, "Error: RX urb failed:%d\n", urb->status);
    if (WARN_ONCE(q->e[q->end].urb != urb, "RX urb mismatch"))
        goto out;
    q->end = (q->end + 1) % q->entries;
    q->pending++;
    tasklet_schedule(&dev->rx_tasklet);
out:
    spin_unlock_irqrestore(&dev->rx_lock, flags);
}
static void mt7601u_rx_tasklet(unsigned long data)
{
    struct mt7601u_dev *dev = (struct mt7601u_dev *) data;
    struct mt7601u_dma_buf_rx *e;
    while ((e = mt7601u_rx_get_pending_entry(dev))) {
        if (e->urb->status)
            continue;
        mt7601u_rx_process_entry(dev, e);
        mt7601u_submit_rx_buf(dev, e, GFP_ATOMIC);
    }
}
static void mt7601u_complete_tx(struct urb *urb)
{
    struct mt7601u_tx_queue *q = urb->context;
    struct mt7601u_dev *dev = q->dev;
    struct sk_buff *skb;
    unsigned long flags;
    spin_lock_irqsave(&dev->tx_lock, flags);
    if (mt7601u_urb_has_error(urb))
        dev_err(dev->dev, "Error: TX urb failed:%d\n", urb->status);
    if (WARN_ONCE(q->e[q->start].urb != urb, "TX urb mismatch"))
        goto out;
    skb = q->e[q->start].skb;
    trace_mt_tx_dma_done(dev, skb);
    __skb_queue_tail(&dev->tx_skb_done, skb);
    tasklet_schedule(&dev->tx_tasklet);
    if (q->used == q->entries - q->entries / 8)
        ieee80211_wake_queue(dev->hw, skb_get_queue_mapping(skb));
    q->start = (q->start + 1) % q->entries;
    q->used--;
out:
    spin_unlock_irqrestore(&dev->tx_lock, flags);
}
static void mt7601u_tx_tasklet(unsigned long data)
{
    struct mt7601u_dev *dev = (struct mt7601u_dev *) data;
    struct sk_buff_head skbs;
    unsigned long flags;
    __skb_queue_head_init(&skbs);
    spin_lock_irqsave(&dev->tx_lock, flags);
    set_bit(MT7601U_STATE_MORE_STATS, &dev->state);
    if (!test_and_set_bit(MT7601U_STATE_READING_STATS, &dev->state))
        queue_delayed_work(dev->stat_wq, &dev->stat_work,
                   msecs_to_jiffies(10));
    skb_queue_splice_init(&dev->tx_skb_done, &skbs);
    spin_unlock_irqrestore(&dev->tx_lock, flags);
    while (!skb_queue_empty(&skbs)) {
        struct sk_buff *skb = __skb_dequeue(&skbs);
        mt7601u_tx_status(dev, skb);
    }
}
static int mt7601u_dma_submit_tx(struct mt7601u_dev *dev,
                 struct sk_buff *skb, u8 ep)
{
    struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
    unsigned snd_pipe = usb_sndbulkpipe(usb_dev, dev->out_eps[ep]);
    struct mt7601u_dma_buf_tx *e;
    struct mt7601u_tx_queue *q = &dev->tx_q[ep];
    unsigned long flags;
    int ret;
    spin_lock_irqsave(&dev->tx_lock, flags);
    if (WARN_ON(q->entries <= q->used)) {
        ret = -ENOSPC;
        goto out;
    }
    e = &q->e[q->end];
    e->skb = skb;
    usb_fill_bulk_urb(e->urb, usb_dev, snd_pipe, skb->data, skb->len,
              mt7601u_complete_tx, q);
    ret = usb_submit_urb(e->urb, GFP_ATOMIC);
    if (ret) {
        /* Special-handle ENODEV from TX urb submission because it will
         * often be the first ENODEV we see after device is removed.
         */
        if (ret == -ENODEV)
            set_bit(MT7601U_STATE_REMOVED, &dev->state);
        else
            dev_err(dev->dev, "Error: TX urb submit failed:%d\n",
                ret);
        goto out;
    }
    q->end = (q->end + 1) % q->entries;
    q->used++;
    if (q->used >= q->entries)
        ieee80211_stop_queue(dev->hw, skb_get_queue_mapping(skb));
out:
    spin_unlock_irqrestore(&dev->tx_lock, flags);
    return ret;
}
/* Map hardware Q to USB endpoint number */
static u8 q2ep(u8 qid)
{
    /* TODO: take management packets to queue 5 */
    return qid + 1;
}
/* Map USB endpoint number to Q id in the DMA engine */
static enum mt76_qsel ep2dmaq(u8 ep)
{
    if (ep == 5)
        return MT_QSEL_MGMT;
    return MT_QSEL_EDCA;
}
int mt7601u_dma_enqueue_tx(struct mt7601u_dev *dev, struct sk_buff *skb,
               struct mt76_wcid *wcid, int hw_q)
{
    u8 ep = q2ep(hw_q);
    u32 dma_flags;
    int ret;
    dma_flags = MT_TXD_PKT_INFO_80211;
    if (wcid->hw_key_idx == 0xff)
        dma_flags |= MT_TXD_PKT_INFO_WIV;
    ret = mt7601u_dma_skb_wrap_pkt(skb, ep2dmaq(ep), dma_flags);
    if (ret)
        return ret;
    ret = mt7601u_dma_submit_tx(dev, skb, ep);
    if (ret) {
        ieee80211_free_txskb(dev->hw, skb);
        return ret;
    }
    return 0;
}
static void mt7601u_kill_rx(struct mt7601u_dev *dev)
{
    int i;
    unsigned long flags;
    spin_lock_irqsave(&dev->rx_lock, flags);
    for (i = 0; i < dev->rx_q.entries; i++) {
        int next = dev->rx_q.end;
        spin_unlock_irqrestore(&dev->rx_lock, flags);
        usb_poison_urb(dev->rx_q.e[next].urb);
        spin_lock_irqsave(&dev->rx_lock, flags);
    }
    spin_unlock_irqrestore(&dev->rx_lock, flags);
}
static int mt7601u_submit_rx_buf(struct mt7601u_dev *dev,
                 struct mt7601u_dma_buf_rx *e, gfp_t gfp)
{
    struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
    u8 *buf = page_address(e->p);
    unsigned pipe;
    int ret;
    pipe = usb_rcvbulkpipe(usb_dev, dev->in_eps[MT_EP_IN_PKT_RX]);
    usb_fill_bulk_urb(e->urb, usb_dev, pipe, buf, MT_RX_URB_SIZE,
              mt7601u_complete_rx, dev);
    trace_mt_submit_urb(dev, e->urb);
    ret = usb_submit_urb(e->urb, gfp);
    if (ret)
        dev_err(dev->dev, "Error: submit RX URB failed:%d\n", ret);
    return ret;
}
static int mt7601u_submit_rx(struct mt7601u_dev *dev)
{
    int i, ret;
    for (i = 0; i < dev->rx_q.entries; i++) {
        ret = mt7601u_submit_rx_buf(dev, &dev->rx_q.e[i], GFP_KERNEL);
        if (ret)
            return ret;
    }
    return 0;
}
static void mt7601u_free_rx(struct mt7601u_dev *dev)
{
    int i;
    for (i = 0; i < dev->rx_q.entries; i++) {
        __free_pages(dev->rx_q.e[i].p, MT_RX_ORDER);
        usb_free_urb(dev->rx_q.e[i].urb);
    }
}
static int mt7601u_alloc_rx(struct mt7601u_dev *dev)
{
    int i;
    memset(&dev->rx_q, 0, sizeof(dev->rx_q));
    dev->rx_q.dev = dev;
    dev->rx_q.entries = N_RX_ENTRIES;
    for (i = 0; i < N_RX_ENTRIES; i++) {
        dev->rx_q.e[i].urb = usb_alloc_urb(0, GFP_KERNEL);
        dev->rx_q.e[i].p = dev_alloc_pages(MT_RX_ORDER);
        if (!dev->rx_q.e[i].urb || !dev->rx_q.e[i].p)
            return -ENOMEM;
    }
    return 0;
}
static void mt7601u_free_tx_queue(struct mt7601u_tx_queue *q)
{
    int i;
    WARN_ON(q->used);
    for (i = 0; i < q->entries; i++)  {
        usb_poison_urb(q->e[i].urb);
        usb_free_urb(q->e[i].urb);
    }
}
static void mt7601u_free_tx(struct mt7601u_dev *dev)
{
    int i;
    for (i = 0; i < __MT_EP_OUT_MAX; i++)
        mt7601u_free_tx_queue(&dev->tx_q[i]);
}
static int mt7601u_alloc_tx_queue(struct mt7601u_dev *dev,
                  struct mt7601u_tx_queue *q)
{
    int i;
    q->dev = dev;
    q->entries = N_TX_ENTRIES;
    for (i = 0; i < N_TX_ENTRIES; i++) {
        q->e[i].urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!q->e[i].urb)
            return -ENOMEM;
    }
    return 0;
}
static int mt7601u_alloc_tx(struct mt7601u_dev *dev)
{
    int i;
    dev->tx_q = devm_kcalloc(dev->dev, __MT_EP_OUT_MAX,
                 sizeof(*dev->tx_q), GFP_KERNEL);
    for (i = 0; i < __MT_EP_OUT_MAX; i++)
        if (mt7601u_alloc_tx_queue(dev, &dev->tx_q[i]))
            return -ENOMEM;
    return 0;
}
int mt7601u_dma_init(struct mt7601u_dev *dev)
{
    int ret = -ENOMEM;
    tasklet_init(&dev->tx_tasklet, mt7601u_tx_tasklet, (unsigned long) dev);
    tasklet_init(&dev->rx_tasklet, mt7601u_rx_tasklet, (unsigned long) dev);
    ret = mt7601u_alloc_tx(dev);
    if (ret)
        goto err;
    ret = mt7601u_alloc_rx(dev);
    if (ret)
        goto err;
    ret = mt7601u_submit_rx(dev);
    if (ret)
        goto err;
    return 0;
err:
    mt7601u_dma_cleanup(dev);
    return ret;
}
void mt7601u_dma_cleanup(struct mt7601u_dev *dev)
{
    mt7601u_kill_rx(dev);
    tasklet_kill(&dev->rx_tasklet);
    mt7601u_free_rx(dev);
    mt7601u_free_tx(dev);
    tasklet_kill(&dev->tx_tasklet);
}
linux-bsp/drivers/mt7601u-sta/dma.h
New file
@@ -0,0 +1,127 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#ifndef __MT7601U_DMA_H
#define __MT7601U_DMA_H
#include <asm/unaligned.h>
#include <linux/skbuff.h>
#include "util.h"
#define MT_DMA_HDR_LEN            4
#define MT_RX_INFO_LEN            4
#define MT_FCE_INFO_LEN            4
#define MT_DMA_HDRS            (MT_DMA_HDR_LEN + MT_RX_INFO_LEN)
/* Common Tx DMA descriptor fields */
#define MT_TXD_INFO_LEN            GENMASK(15, 0)
#define MT_TXD_INFO_D_PORT        GENMASK(29, 27)
#define MT_TXD_INFO_TYPE        GENMASK(31, 30)
enum mt76_msg_port {
    WLAN_PORT,
    CPU_RX_PORT,
    CPU_TX_PORT,
    HOST_PORT,
    VIRTUAL_CPU_RX_PORT,
    VIRTUAL_CPU_TX_PORT,
    DISCARD,
};
enum mt76_info_type {
    DMA_PACKET,
    DMA_COMMAND,
};
/* Tx DMA packet specific flags */
#define MT_TXD_PKT_INFO_NEXT_VLD    BIT(16)
#define MT_TXD_PKT_INFO_TX_BURST    BIT(17)
#define MT_TXD_PKT_INFO_80211        BIT(19)
#define MT_TXD_PKT_INFO_TSO        BIT(20)
#define MT_TXD_PKT_INFO_CSO        BIT(21)
#define MT_TXD_PKT_INFO_WIV        BIT(24)
#define MT_TXD_PKT_INFO_QSEL        GENMASK(26, 25)
enum mt76_qsel {
    MT_QSEL_MGMT,
    MT_QSEL_HCCA,
    MT_QSEL_EDCA,
    MT_QSEL_EDCA_2,
};
/* Tx DMA MCU command specific flags */
#define MT_TXD_CMD_INFO_SEQ        GENMASK(19, 16)
#define MT_TXD_CMD_INFO_TYPE        GENMASK(26, 20)
static inline int mt7601u_dma_skb_wrap(struct sk_buff *skb,
                       enum mt76_msg_port d_port,
                       enum mt76_info_type type, u32 flags)
{
    u32 info;
    /* Buffer layout:
     *    |   4B   | xfer len |      pad       |  4B  |
     *    | TXINFO | pkt/cmd  | zero pad to 4B | zero |
     *
     * length field of TXINFO should be set to 'xfer len'.
     */
    info = flags |
        MT76_SET(MT_TXD_INFO_LEN, round_up(skb->len, 4)) |
        MT76_SET(MT_TXD_INFO_D_PORT, d_port) |
        MT76_SET(MT_TXD_INFO_TYPE, type);
    put_unaligned_le32(info, skb_push(skb, sizeof(info)));
    return skb_put_padto(skb, round_up(skb->len, 4) + 4);
}
static inline int
mt7601u_dma_skb_wrap_pkt(struct sk_buff *skb, enum mt76_qsel qsel, u32 flags)
{
    flags |= MT76_SET(MT_TXD_PKT_INFO_QSEL, qsel);
    return mt7601u_dma_skb_wrap(skb, WLAN_PORT, DMA_PACKET, flags);
}
/* Common Rx DMA descriptor fields */
#define MT_RXD_INFO_LEN            GENMASK(13, 0)
#define MT_RXD_INFO_PCIE_INTR        BIT(24)
#define MT_RXD_INFO_QSEL        GENMASK(26, 25)
#define MT_RXD_INFO_PORT        GENMASK(29, 27)
#define MT_RXD_INFO_TYPE        GENMASK(31, 30)
/* Rx DMA packet specific flags */
#define MT_RXD_PKT_INFO_UDP_ERR        BIT(16)
#define MT_RXD_PKT_INFO_TCP_ERR        BIT(17)
#define MT_RXD_PKT_INFO_IP_ERR        BIT(18)
#define MT_RXD_PKT_INFO_PKT_80211    BIT(19)
#define MT_RXD_PKT_INFO_L3L4_DONE    BIT(20)
#define MT_RXD_PKT_INFO_MAC_LEN        GENMASK(23, 21)
/* Rx DMA MCU command specific flags */
#define MT_RXD_CMD_INFO_SELF_GEN    BIT(15)
#define MT_RXD_CMD_INFO_CMD_SEQ        GENMASK(19, 16)
#define MT_RXD_CMD_INFO_EVT_TYPE    GENMASK(23, 20)
enum mt76_evt_type {
    CMD_DONE,
    CMD_ERROR,
    CMD_RETRY,
    EVENT_PWR_RSP,
    EVENT_WOW_RSP,
    EVENT_CARRIER_DETECT_RSP,
    EVENT_DFS_DETECT_RSP,
};
#endif
linux-bsp/drivers/mt7601u-sta/eeprom.c
New file
@@ -0,0 +1,418 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#include <linux/of.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
#include "mt7601u.h"
#include "eeprom.h"
static bool
field_valid(u8 val)
{
    return val != 0xff;
}
static s8
field_validate(u8 val)
{
    if (!field_valid(val))
        return 0;
    return val;
}
static int
mt7601u_efuse_read(struct mt7601u_dev *dev, u16 addr, u8 *data,
           enum mt7601u_eeprom_access_modes mode)
{
    u32 val;
    int i;
    val = mt76_rr(dev, MT_EFUSE_CTRL);
    val &= ~(MT_EFUSE_CTRL_AIN |
         MT_EFUSE_CTRL_MODE);
    val |= MT76_SET(MT_EFUSE_CTRL_AIN, addr & ~0xf) |
           MT76_SET(MT_EFUSE_CTRL_MODE, mode) |
           MT_EFUSE_CTRL_KICK;
    mt76_wr(dev, MT_EFUSE_CTRL, val);
    if (!mt76_poll(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
        return -ETIMEDOUT;
    val = mt76_rr(dev, MT_EFUSE_CTRL);
    if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) {
        /* Parts of eeprom not in the usage map (0x80-0xc0,0xf0)
         * will not return valid data but it's ok.
         */
        memset(data, 0xff, 16);
        return 0;
    }
    for (i = 0; i < 4; i++) {
        val = mt76_rr(dev, MT_EFUSE_DATA(i));
        put_unaligned_le32(val, data + 4 * i);
    }
    return 0;
}
static int
mt7601u_efuse_physical_size_check(struct mt7601u_dev *dev)
{
    const int map_reads = DIV_ROUND_UP(MT_EFUSE_USAGE_MAP_SIZE, 16);
    u8 data[map_reads * 16];
    int ret, i;
    u32 start = 0, end = 0, cnt_free;
    for (i = 0; i < map_reads; i++) {
        ret = mt7601u_efuse_read(dev, MT_EE_USAGE_MAP_START + i * 16,
                     data + i * 16, MT_EE_PHYSICAL_READ);
        if (ret)
            return ret;
    }
    for (i = 0; i < MT_EFUSE_USAGE_MAP_SIZE; i++)
        if (!data[i]) {
            if (!start)
                start = MT_EE_USAGE_MAP_START + i;
            end = MT_EE_USAGE_MAP_START + i;
        }
    cnt_free = end - start + 1;
    if (MT_EFUSE_USAGE_MAP_SIZE - cnt_free < 5) {
        dev_err(dev->dev, "Error: your device needs default EEPROM file and this driver doesn't support it!\n");
        return -EINVAL;
    }
    return 0;
}
static bool
mt7601u_has_tssi(struct mt7601u_dev *dev, u8 *eeprom)
{
    u16 nic_conf1 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_1);
    return ~nic_conf1 && (nic_conf1 & MT_EE_NIC_CONF_1_TX_ALC_EN);
}
static void
mt7601u_set_chip_cap(struct mt7601u_dev *dev, u8 *eeprom)
{
    u16 nic_conf0 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_0);
    u16 nic_conf1 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_1);
    if (!field_valid(nic_conf1 & 0xff))
        nic_conf1 &= 0xff00;
    dev->ee->tssi_enabled = mt7601u_has_tssi(dev, eeprom) &&
                !(nic_conf1 & MT_EE_NIC_CONF_1_TEMP_TX_ALC);
    if (nic_conf1 & MT_EE_NIC_CONF_1_HW_RF_CTRL)
        dev_err(dev->dev,
            "Error: this driver does not support HW RF ctrl\n");
    if (!field_valid(nic_conf0 >> 8))
        return;
    if (MT76_GET(MT_EE_NIC_CONF_0_RX_PATH, nic_conf0) > 1 ||
        MT76_GET(MT_EE_NIC_CONF_0_TX_PATH, nic_conf0) > 1)
        dev_err(dev->dev,
            "Error: device has more than 1 RX/TX stream!\n");
}
static int
mt7601u_set_macaddr(struct mt7601u_dev *dev, const u8 *eeprom)
{
    const void *src = eeprom + MT_EE_MAC_ADDR;
    ether_addr_copy(dev->macaddr, src);
    if (!is_valid_ether_addr(dev->macaddr)) {
        eth_random_addr(dev->macaddr);
        dev_info(dev->dev,
             "Invalid MAC address, using random address %pM\n",
             dev->macaddr);
    }
    mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->macaddr));
    mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(dev->macaddr + 4) |
        MT76_SET(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
    return 0;
}
static void mt7601u_set_channel_target_power(struct mt7601u_dev *dev,
                         u8 *eeprom, u8 max_pwr)
{
    u8 trgt_pwr = eeprom[MT_EE_TX_TSSI_TARGET_POWER];
    if (trgt_pwr > max_pwr || !trgt_pwr) {
        dev_warn(dev->dev, "Error: EEPROM trgt power invalid %hhx!\n",
             trgt_pwr);
        trgt_pwr = 0x20;
    }
    memset(dev->ee->chan_pwr, trgt_pwr, sizeof(dev->ee->chan_pwr));
}
static void
mt7601u_set_channel_power(struct mt7601u_dev *dev, u8 *eeprom)
{
    u32 i, val;
    u8 max_pwr;
    val = mt7601u_rr(dev, MT_TX_ALC_CFG_0);
    max_pwr = MT76_GET(MT_TX_ALC_CFG_0_LIMIT_0, val);
    if (mt7601u_has_tssi(dev, eeprom)) {
        mt7601u_set_channel_target_power(dev, eeprom, max_pwr);
        return;
    }
    for (i = 0; i < 14; i++) {
        s8 power = field_validate(eeprom[MT_EE_TX_POWER_OFFSET + i]);
        if (power > max_pwr || power < 0)
            power = MT7601U_DEFAULT_TX_POWER;
        dev->ee->chan_pwr[i] = power;
    }
}
static void
mt7601u_set_country_reg(struct mt7601u_dev *dev, u8 *eeprom)
{
    /* Note: - region 31 is not valid for mt7601u (see rtmp_init.c)
     *     - comments in rtmp_def.h are incorrect (see rt_channel.c)
     */
    static const struct reg_channel_bounds chan_bounds[] = {
        /* EEPROM country regions 0 - 7 */
        {  1, 11 },    {  1, 13 },    { 10,  2 },    { 10,  4 },
        { 14,  1 },    {  1, 14 },    {  3,  7 },    {  5,  9 },
        /* EEPROM country regions 32 - 33 */
        {  1, 11 },    {  1, 14 }
    };
    u8 val = eeprom[MT_EE_COUNTRY_REGION];
    int idx = -1;
    if (val < 8)
        idx = val;
    if (val > 31 && val < 33)
        idx = val - 32 + 8;
    if (idx != -1)
        dev_info(dev->dev,
             "EEPROM country region %02hhx (channels %hhd-%hhd)\n",
             val, chan_bounds[idx].start,
             chan_bounds[idx].start + chan_bounds[idx].num - 1);
    else
        idx = 5; /* channels 1 - 14 */
    dev->ee->reg = chan_bounds[idx];
    /* TODO: country region 33 is special - phy should be set to B-mode
     *     before entering channel 14 (see sta/connect.c)
     */
}
static void
mt7601u_set_rf_freq_off(struct mt7601u_dev *dev, u8 *eeprom)
{
    u8 comp;
    dev->ee->rf_freq_off = field_validate(eeprom[MT_EE_FREQ_OFFSET]);
    comp = field_validate(eeprom[MT_EE_FREQ_OFFSET_COMPENSATION]);
    if (comp & BIT(7))
        dev->ee->rf_freq_off -= comp & 0x7f;
    else
        dev->ee->rf_freq_off += comp;
}
static void
mt7601u_set_rssi_offset(struct mt7601u_dev *dev, u8 *eeprom)
{
    int i;
    s8 *rssi_offset = dev->ee->rssi_offset;
    for (i = 0; i < 2; i++) {
        rssi_offset[i] = eeprom[MT_EE_RSSI_OFFSET + i];
        if (rssi_offset[i] < -10 || rssi_offset[i] > 10) {
            dev_warn(dev->dev,
                 "Warning: EEPROM RSSI is invalid %02hhx\n",
                 rssi_offset[i]);
            rssi_offset[i] = 0;
        }
    }
}
static void
mt7601u_extra_power_over_mac(struct mt7601u_dev *dev)
{
    u32 val;
    val = ((mt7601u_rr(dev, MT_TX_PWR_CFG_1) & 0x0000ff00) >> 8);
    val |= ((mt7601u_rr(dev, MT_TX_PWR_CFG_2) & 0x0000ff00) << 8);
    mt7601u_wr(dev, MT_TX_PWR_CFG_7, val);
    val = ((mt7601u_rr(dev, MT_TX_PWR_CFG_4) & 0x0000ff00) >> 8);
    mt7601u_wr(dev, MT_TX_PWR_CFG_9, val);
}
static void
mt7601u_set_power_rate(struct power_per_rate *rate, s8 delta, u8 value)
{
    /* Invalid? Note: vendor driver does not handle this */
    if (value == 0xff)
        return;
    rate->raw = s6_validate(value);
    rate->bw20 = s6_to_int(value);
    /* Note: vendor driver does cap the value to s6 right away */
    rate->bw40 = rate->bw20 + delta;
}
static void
mt7601u_save_power_rate(struct mt7601u_dev *dev, s8 delta, u32 val, int i)
{
    struct mt7601u_rate_power *t = &dev->ee->power_rate_table;
    switch (i) {
    case 0:
        mt7601u_set_power_rate(&t->cck[0], delta, (val >> 0) & 0xff);
        mt7601u_set_power_rate(&t->cck[1], delta, (val >> 8) & 0xff);
        /* Save cck bw20 for fixups of channel 14 */
        dev->ee->real_cck_bw20[0] = t->cck[0].bw20;
        dev->ee->real_cck_bw20[1] = t->cck[1].bw20;
        mt7601u_set_power_rate(&t->ofdm[0], delta, (val >> 16) & 0xff);
        mt7601u_set_power_rate(&t->ofdm[1], delta, (val >> 24) & 0xff);
        break;
    case 1:
        mt7601u_set_power_rate(&t->ofdm[2], delta, (val >> 0) & 0xff);
        mt7601u_set_power_rate(&t->ofdm[3], delta, (val >> 8) & 0xff);
        mt7601u_set_power_rate(&t->ht[0], delta, (val >> 16) & 0xff);
        mt7601u_set_power_rate(&t->ht[1], delta, (val >> 24) & 0xff);
        break;
    case 2:
        mt7601u_set_power_rate(&t->ht[2], delta, (val >> 0) & 0xff);
        mt7601u_set_power_rate(&t->ht[3], delta, (val >> 8) & 0xff);
        break;
    }
}
static s8
get_delta(u8 val)
{
    s8 ret;
    if (!field_valid(val) || !(val & BIT(7)))
        return 0;
    ret = val & 0x1f;
    if (ret > 8)
        ret = 8;
    if (val & BIT(6))
        ret = -ret;
    return ret;
}
static void
mt7601u_config_tx_power_per_rate(struct mt7601u_dev *dev, u8 *eeprom)
{
    u32 val;
    s8 bw40_delta;
    int i;
    bw40_delta = get_delta(eeprom[MT_EE_TX_POWER_DELTA_BW40]);
    for (i = 0; i < 5; i++) {
        val = get_unaligned_le32(eeprom + MT_EE_TX_POWER_BYRATE(i));
        mt7601u_save_power_rate(dev, bw40_delta, val, i);
        if (~val)
            mt7601u_wr(dev, MT_TX_PWR_CFG_0 + i * 4, val);
    }
    mt7601u_extra_power_over_mac(dev);
}
static void
mt7601u_init_tssi_params(struct mt7601u_dev *dev, u8 *eeprom)
{
    struct tssi_data *d = &dev->ee->tssi_data;
    if (!dev->ee->tssi_enabled)
        return;
    d->slope = eeprom[MT_EE_TX_TSSI_SLOPE];
    d->tx0_delta_offset = eeprom[MT_EE_TX_TSSI_OFFSET] * 1024;
    d->offset[0] = eeprom[MT_EE_TX_TSSI_OFFSET_GROUP];
    d->offset[1] = eeprom[MT_EE_TX_TSSI_OFFSET_GROUP + 1];
    d->offset[2] = eeprom[MT_EE_TX_TSSI_OFFSET_GROUP + 2];
}
int
mt7601u_eeprom_init(struct mt7601u_dev *dev)
{
    u8 *eeprom;
    int i, ret;
    ret = mt7601u_efuse_physical_size_check(dev);
    if (ret)
        return ret;
    dev->ee = devm_kzalloc(dev->dev, sizeof(*dev->ee), GFP_KERNEL);
    if (!dev->ee)
        return -ENOMEM;
    eeprom = kmalloc(MT7601U_EEPROM_SIZE, GFP_KERNEL);
    if (!eeprom)
        return -ENOMEM;
    for (i = 0; i + 16 <= MT7601U_EEPROM_SIZE; i += 16) {
        ret = mt7601u_efuse_read(dev, i, eeprom + i, MT_EE_READ);
        if (ret)
            goto out;
    }
    if (eeprom[MT_EE_VERSION_EE] > MT7601U_EE_MAX_VER)
        dev_warn(dev->dev,
             "Warning: unsupported EEPROM version %02hhx\n",
             eeprom[MT_EE_VERSION_EE]);
    dev_info(dev->dev, "EEPROM ver:%02hhx fae:%02hhx\n",
         eeprom[MT_EE_VERSION_EE], eeprom[MT_EE_VERSION_FAE]);
    mt7601u_set_macaddr(dev, eeprom);
    mt7601u_set_chip_cap(dev, eeprom);
    mt7601u_set_channel_power(dev, eeprom);
    mt7601u_set_country_reg(dev, eeprom);
    mt7601u_set_rf_freq_off(dev, eeprom);
    mt7601u_set_rssi_offset(dev, eeprom);
    dev->ee->ref_temp = eeprom[MT_EE_REF_TEMP];
    dev->ee->lna_gain = eeprom[MT_EE_LNA_GAIN];
    mt7601u_config_tx_power_per_rate(dev, eeprom);
    mt7601u_init_tssi_params(dev, eeprom);
out:
    kfree(eeprom);
    return ret;
}
linux-bsp/drivers/mt7601u-sta/eeprom.h
New file
@@ -0,0 +1,151 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#ifndef __MT7601U_EEPROM_H
#define __MT7601U_EEPROM_H
struct mt7601u_dev;
#define MT7601U_EE_MAX_VER            0x0c
#define MT7601U_EEPROM_SIZE            256
#define MT7601U_DEFAULT_TX_POWER        6
enum mt76_eeprom_field {
    MT_EE_CHIP_ID =                0x00,
    MT_EE_VERSION_FAE =            0x02,
    MT_EE_VERSION_EE =            0x03,
    MT_EE_MAC_ADDR =            0x04,
    MT_EE_NIC_CONF_0 =            0x34,
    MT_EE_NIC_CONF_1 =            0x36,
    MT_EE_COUNTRY_REGION =            0x39,
    MT_EE_FREQ_OFFSET =            0x3a,
    MT_EE_NIC_CONF_2 =            0x42,
    MT_EE_LNA_GAIN =            0x44,
    MT_EE_RSSI_OFFSET =            0x46,
    MT_EE_TX_POWER_DELTA_BW40 =        0x50,
    MT_EE_TX_POWER_OFFSET =            0x52,
    MT_EE_TX_TSSI_SLOPE =            0x6e,
    MT_EE_TX_TSSI_OFFSET_GROUP =        0x6f,
    MT_EE_TX_TSSI_OFFSET =            0x76,
    MT_EE_TX_TSSI_TARGET_POWER =        0xd0,
    MT_EE_REF_TEMP =            0xd1,
    MT_EE_FREQ_OFFSET_COMPENSATION =    0xdb,
    MT_EE_TX_POWER_BYRATE_BASE =        0xde,
    MT_EE_USAGE_MAP_START =            0x1e0,
    MT_EE_USAGE_MAP_END =            0x1fc,
};
#define MT_EE_NIC_CONF_0_RX_PATH        GENMASK(3, 0)
#define MT_EE_NIC_CONF_0_TX_PATH        GENMASK(7, 4)
#define MT_EE_NIC_CONF_0_BOARD_TYPE        GENMASK(13, 12)
#define MT_EE_NIC_CONF_1_HW_RF_CTRL        BIT(0)
#define MT_EE_NIC_CONF_1_TEMP_TX_ALC        BIT(1)
#define MT_EE_NIC_CONF_1_LNA_EXT_2G        BIT(2)
#define MT_EE_NIC_CONF_1_LNA_EXT_5G        BIT(3)
#define MT_EE_NIC_CONF_1_TX_ALC_EN        BIT(13)
#define MT_EE_NIC_CONF_2_RX_STREAM        GENMASK(3, 0)
#define MT_EE_NIC_CONF_2_TX_STREAM        GENMASK(7, 4)
#define MT_EE_NIC_CONF_2_HW_ANTDIV        BIT(8)
#define MT_EE_NIC_CONF_2_XTAL_OPTION        GENMASK(10, 9)
#define MT_EE_NIC_CONF_2_TEMP_DISABLE        BIT(11)
#define MT_EE_NIC_CONF_2_COEX_METHOD        GENMASK(15, 13)
#define MT_EE_TX_POWER_BYRATE(i)        (MT_EE_TX_POWER_BYRATE_BASE + \
                         (i) * 4)
#define MT_EFUSE_USAGE_MAP_SIZE            (MT_EE_USAGE_MAP_END -    \
                         MT_EE_USAGE_MAP_START + 1)
enum mt7601u_eeprom_access_modes {
    MT_EE_READ = 0,
    MT_EE_PHYSICAL_READ = 1,
};
struct power_per_rate  {
    u8 raw;  /* validated s6 value */
    s8 bw20; /* sign-extended int */
    s8 bw40; /* sign-extended int */
};
/* Power per rate - one value per two rates */
struct mt7601u_rate_power {
    struct power_per_rate cck[2];
    struct power_per_rate ofdm[4];
    struct power_per_rate ht[4];
};
struct reg_channel_bounds {
    u8 start;
    u8 num;
};
struct mt7601u_eeprom_params {
    bool tssi_enabled;
    u8 rf_freq_off;
    s8 rssi_offset[2];
    s8 ref_temp;
    s8 lna_gain;
    u8 chan_pwr[14];
    struct mt7601u_rate_power power_rate_table;
    s8 real_cck_bw20[2];
    /* TSSI stuff - only with internal TX ALC */
    struct tssi_data {
        int tx0_delta_offset;
        u8 slope;
        u8 offset[3];
    } tssi_data;
    struct reg_channel_bounds reg;
};
int mt7601u_eeprom_init(struct mt7601u_dev *dev);
static inline u32 s6_validate(u32 reg)
{
    WARN_ON(reg & ~GENMASK(5, 0));
    return reg & GENMASK(5, 0);
}
static inline int s6_to_int(u32 reg)
{
    int s6;
    s6 = s6_validate(reg);
    if (s6 & BIT(5))
        s6 -= BIT(6);
    return s6;
}
static inline u32 int_to_s6(int val)
{
    if (val < -0x20)
        return 0x20;
    if (val > 0x1f)
        return 0x1f;
    return val & 0x3f;
}
#endif
linux-bsp/drivers/mt7601u-sta/init.c
New file
@@ -0,0 +1,639 @@
/*
 * (c) Copyright 2002-2010, Ralink Technology, Inc.
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#include <linux/version.h>
#include "mt7601u.h"
#include "eeprom.h"
#include "trace.h"
#include "mcu.h"
#include "initvals.h"
static void
mt7601u_set_wlan_state(struct mt7601u_dev *dev, u32 val, bool enable)
{
    int i;
    /* Note: we don't turn off WLAN_CLK because that makes the device
     *     not respond properly on the probe path.
     *     In case anyone (PSM?) wants to use this function we can
     *     bring the clock stuff back and fixup the probe path.
     */
    if (enable)
        val |= (MT_WLAN_FUN_CTRL_WLAN_EN |
            MT_WLAN_FUN_CTRL_WLAN_CLK_EN);
    else
        val &= ~(MT_WLAN_FUN_CTRL_WLAN_EN);
    mt7601u_wr(dev, MT_WLAN_FUN_CTRL, val);
    udelay(20);
    if (enable) {
        set_bit(MT7601U_STATE_WLAN_RUNNING, &dev->state);
    } else {
        clear_bit(MT7601U_STATE_WLAN_RUNNING, &dev->state);
        return;
    }
    for (i = 200; i; i--) {
        val = mt7601u_rr(dev, MT_CMB_CTRL);
        if (val & MT_CMB_CTRL_XTAL_RDY && val & MT_CMB_CTRL_PLL_LD)
            break;
        udelay(20);
    }
    /* Note: vendor driver tries to disable/enable wlan here and retry
     *       but the code which does it is so buggy it must have never
     *       triggered, so don't bother.
     */
    if (!i)
        dev_err(dev->dev, "Error: PLL and XTAL check failed!\n");
}
static void mt7601u_chip_onoff(struct mt7601u_dev *dev, bool enable, bool reset)
{
    u32 val;
    mutex_lock(&dev->hw_atomic_mutex);
    val = mt7601u_rr(dev, MT_WLAN_FUN_CTRL);
    if (reset) {
        val |= MT_WLAN_FUN_CTRL_GPIO_OUT_EN;
        val &= ~MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL;
        if (val & MT_WLAN_FUN_CTRL_WLAN_EN) {
            val |= (MT_WLAN_FUN_CTRL_WLAN_RESET |
                MT_WLAN_FUN_CTRL_WLAN_RESET_RF);
            mt7601u_wr(dev, MT_WLAN_FUN_CTRL, val);
            udelay(20);
            val &= ~(MT_WLAN_FUN_CTRL_WLAN_RESET |
                 MT_WLAN_FUN_CTRL_WLAN_RESET_RF);
        }
    }
    mt7601u_wr(dev, MT_WLAN_FUN_CTRL, val);
    udelay(20);
    mt7601u_set_wlan_state(dev, val, enable);
    mutex_unlock(&dev->hw_atomic_mutex);
}
static void mt7601u_reset_csr_bbp(struct mt7601u_dev *dev)
{
    mt7601u_wr(dev, MT_MAC_SYS_CTRL, (MT_MAC_SYS_CTRL_RESET_CSR |
                      MT_MAC_SYS_CTRL_RESET_BBP));
    mt7601u_wr(dev, MT_USB_DMA_CFG, 0);
    msleep(1);
    mt7601u_wr(dev, MT_MAC_SYS_CTRL, 0);
}
static void mt7601u_init_usb_dma(struct mt7601u_dev *dev)
{
    u32 val;
    val = MT76_SET(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, MT_USB_AGGR_TIMEOUT) |
          MT76_SET(MT_USB_DMA_CFG_RX_BULK_AGG_LMT, MT_USB_AGGR_SIZE_LIMIT) |
          MT_USB_DMA_CFG_RX_BULK_EN |
          MT_USB_DMA_CFG_TX_BULK_EN;
    if (dev->in_max_packet == 512)
        val |= MT_USB_DMA_CFG_RX_BULK_AGG_EN;
    mt7601u_wr(dev, MT_USB_DMA_CFG, val);
    val |= MT_USB_DMA_CFG_UDMA_RX_WL_DROP;
    mt7601u_wr(dev, MT_USB_DMA_CFG, val);
    val &= ~MT_USB_DMA_CFG_UDMA_RX_WL_DROP;
    mt7601u_wr(dev, MT_USB_DMA_CFG, val);
}
static int mt7601u_init_bbp(struct mt7601u_dev *dev)
{
    int ret;
    ret = mt7601u_wait_bbp_ready(dev);
    if (ret)
        return ret;
    ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP, bbp_common_vals,
                      ARRAY_SIZE(bbp_common_vals));
    if (ret)
        return ret;
    return mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP, bbp_chip_vals,
                       ARRAY_SIZE(bbp_chip_vals));
}
static void
mt76_init_beacon_offsets(struct mt7601u_dev *dev)
{
    u16 base = MT_BEACON_BASE;
    u32 regs[4] = {};
    int i;
    for (i = 0; i < 16; i++) {
        u16 addr = dev->beacon_offsets[i];
        regs[i / 4] |= ((addr - base) / 64) << (8 * (i % 4));
    }
    for (i = 0; i < 4; i++)
        mt7601u_wr(dev, MT_BCN_OFFSET(i), regs[i]);
}
static int mt7601u_write_mac_initvals(struct mt7601u_dev *dev)
{
    int ret;
    ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_WLAN, mac_common_vals,
                      ARRAY_SIZE(mac_common_vals));
    if (ret)
        return ret;
    ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_WLAN,
                      mac_chip_vals, ARRAY_SIZE(mac_chip_vals));
    if (ret)
        return ret;
    mt76_init_beacon_offsets(dev);
    mt7601u_wr(dev, MT_AUX_CLK_CFG, 0);
    return 0;
}
static int mt7601u_init_wcid_mem(struct mt7601u_dev *dev)
{
    u32 *vals;
    int i, ret;
    vals = kmalloc(sizeof(*vals) * N_WCIDS * 2, GFP_KERNEL);
    if (!vals)
        return -ENOMEM;
    for (i = 0; i < N_WCIDS; i++)  {
        vals[i * 2] = 0xffffffff;
        vals[i * 2 + 1] = 0x00ffffff;
    }
    ret = mt7601u_burst_write_regs(dev, MT_WCID_ADDR_BASE,
                       vals, N_WCIDS * 2);
    kfree(vals);
    return ret;
}
static int mt7601u_init_key_mem(struct mt7601u_dev *dev)
{
    u32 vals[4] = {};
    return mt7601u_burst_write_regs(dev, MT_SKEY_MODE_BASE_0,
                    vals, ARRAY_SIZE(vals));
}
static int mt7601u_init_wcid_attr_mem(struct mt7601u_dev *dev)
{
    u32 *vals;
    int i, ret;
    vals = kmalloc(sizeof(*vals) * N_WCIDS * 2, GFP_KERNEL);
    if (!vals)
        return -ENOMEM;
    for (i = 0; i < N_WCIDS * 2; i++)
        vals[i] = 1;
    ret = mt7601u_burst_write_regs(dev, MT_WCID_ATTR_BASE,
                       vals, N_WCIDS * 2);
    kfree(vals);
    return ret;
}
static void mt7601u_reset_counters(struct mt7601u_dev *dev)
{
    mt7601u_rr(dev, MT_RX_STA_CNT0);
    mt7601u_rr(dev, MT_RX_STA_CNT1);
    mt7601u_rr(dev, MT_RX_STA_CNT2);
    mt7601u_rr(dev, MT_TX_STA_CNT0);
    mt7601u_rr(dev, MT_TX_STA_CNT1);
    mt7601u_rr(dev, MT_TX_STA_CNT2);
}
int mt7601u_mac_start(struct mt7601u_dev *dev)
{
    mt7601u_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
    if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
               MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 200000))
        return -ETIMEDOUT;
    dev->rxfilter = MT_RX_FILTR_CFG_CRC_ERR |
        MT_RX_FILTR_CFG_PHY_ERR | MT_RX_FILTR_CFG_PROMISC |
        MT_RX_FILTR_CFG_VER_ERR | MT_RX_FILTR_CFG_DUP |
        MT_RX_FILTR_CFG_CFACK | MT_RX_FILTR_CFG_CFEND |
        MT_RX_FILTR_CFG_ACK | MT_RX_FILTR_CFG_CTS |
        MT_RX_FILTR_CFG_RTS | MT_RX_FILTR_CFG_PSPOLL |
        MT_RX_FILTR_CFG_BA | MT_RX_FILTR_CFG_CTRL_RSV;
    mt7601u_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter);
    mt7601u_wr(dev, MT_MAC_SYS_CTRL,
           MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
    if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
               MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 50))
        return -ETIMEDOUT;
    return 0;
}
static void mt7601u_mac_stop_hw(struct mt7601u_dev *dev)
{
    int i, ok;
    if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
        return;
    mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN |
           MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN |
           MT_BEACON_TIME_CFG_BEACON_TX);
    if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000))
        dev_warn(dev->dev, "Warning: TX DMA did not stop!\n");
    /* Page count on TxQ */
    i = 200;
    while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) ||
               (mt76_rr(dev, 0x0a30) & 0x000000ff) ||
               (mt76_rr(dev, 0x0a34) & 0x00ff00ff)))
        msleep(10);
    if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_TX, 0, 1000))
        dev_warn(dev->dev, "Warning: MAC TX did not stop!\n");
    mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_RX |
                     MT_MAC_SYS_CTRL_ENABLE_TX);
    /* Page count on RxQ */
    ok = 0;
    i = 200;
    while (i--) {
        if (!(mt76_rr(dev, MT_RXQ_STA) & 0x00ff0000) &&
            !mt76_rr(dev, 0x0a30) &&
            !mt76_rr(dev, 0x0a34)) {
            if (ok++ > 5)
                break;
            continue;
        }
        msleep(1);
    }
    if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_RX, 0, 1000))
        dev_warn(dev->dev, "Warning: MAC RX did not stop!\n");
    if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_RX_BUSY, 0, 1000))
        dev_warn(dev->dev, "Warning: RX DMA did not stop!\n");
}
void mt7601u_mac_stop(struct mt7601u_dev *dev)
{
    mt7601u_mac_stop_hw(dev);
    flush_delayed_work(&dev->stat_work);
    cancel_delayed_work_sync(&dev->stat_work);
}
static void mt7601u_stop_hardware(struct mt7601u_dev *dev)
{
    mt7601u_chip_onoff(dev, false, false);
}
int mt7601u_init_hardware(struct mt7601u_dev *dev)
{
    static const u16 beacon_offsets[16] = {
        /* 512 byte per beacon */
        0xc000,    0xc200,    0xc400,    0xc600,
        0xc800,    0xca00,    0xcc00,    0xce00,
        0xd000,    0xd200,    0xd400,    0xd600,
        0xd800,    0xda00,    0xdc00,    0xde00
    };
    int ret;
    dev->beacon_offsets = beacon_offsets;
    mt7601u_chip_onoff(dev, true, false);
    ret = mt7601u_wait_asic_ready(dev);
    if (ret)
        goto err;
    ret = mt7601u_mcu_init(dev);
    if (ret)
        goto err;
    if (!mt76_poll_msec(dev, MT_WPDMA_GLO_CFG,
                MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
                MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 100)) {
        ret = -EIO;
        goto err;
    }
    /* Wait for ASIC ready after FW load. */
    ret = mt7601u_wait_asic_ready(dev);
    if (ret)
        goto err;
    mt7601u_reset_csr_bbp(dev);
    mt7601u_init_usb_dma(dev);
    ret = mt7601u_mcu_cmd_init(dev);
    if (ret)
        goto err;
    ret = mt7601u_dma_init(dev);
    if (ret)
        goto err_mcu;
    ret = mt7601u_write_mac_initvals(dev);
    if (ret)
        goto err_rx;
    if (!mt76_poll_msec(dev, MT_MAC_STATUS,
                MT_MAC_STATUS_TX | MT_MAC_STATUS_RX, 0, 100)) {
        ret = -EIO;
        goto err_rx;
    }
    ret = mt7601u_init_bbp(dev);
    if (ret)
        goto err_rx;
    ret = mt7601u_init_wcid_mem(dev);
    if (ret)
        goto err_rx;
    ret = mt7601u_init_key_mem(dev);
    if (ret)
        goto err_rx;
    ret = mt7601u_init_wcid_attr_mem(dev);
    if (ret)
        goto err_rx;
    mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN |
                         MT_BEACON_TIME_CFG_SYNC_MODE |
                         MT_BEACON_TIME_CFG_TBTT_EN |
                         MT_BEACON_TIME_CFG_BEACON_TX));
    mt7601u_reset_counters(dev);
    mt7601u_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
    mt7601u_wr(dev, MT_TXOP_CTRL_CFG, MT76_SET(MT_TXOP_TRUN_EN, 0x3f) |
                      MT76_SET(MT_TXOP_EXT_CCA_DLY, 0x58));
    ret = mt7601u_eeprom_init(dev);
    if (ret)
        goto err_rx;
    ret = mt7601u_phy_init(dev);
    if (ret)
        goto err_rx;
    mt7601u_set_rx_path(dev, 0);
    mt7601u_set_tx_dac(dev, 0);
    mt7601u_mac_set_ctrlch(dev, false);
    mt7601u_bbp_set_ctrlch(dev, false);
    mt7601u_bbp_set_bw(dev, MT_BW_20);
    return 0;
err_rx:
    mt7601u_dma_cleanup(dev);
err_mcu:
    mt7601u_mcu_cmd_deinit(dev);
err:
    mt7601u_chip_onoff(dev, false, false);
    return ret;
}
void mt7601u_cleanup(struct mt7601u_dev *dev)
{
    if (!test_and_clear_bit(MT7601U_STATE_INITIALIZED, &dev->state))
        return;
    mt7601u_stop_hardware(dev);
    mt7601u_dma_cleanup(dev);
    mt7601u_mcu_cmd_deinit(dev);
}
struct mt7601u_dev *mt7601u_alloc_device(struct device *pdev)
{
    struct ieee80211_hw *hw;
    struct mt7601u_dev *dev;
    hw = ieee80211_alloc_hw(sizeof(*dev), &mt7601u_ops);
    if (!hw)
        return NULL;
    dev = hw->priv;
    dev->dev = pdev;
    dev->hw = hw;
    mutex_init(&dev->vendor_req_mutex);
    mutex_init(&dev->reg_atomic_mutex);
    mutex_init(&dev->hw_atomic_mutex);
    mutex_init(&dev->mutex);
    spin_lock_init(&dev->tx_lock);
    spin_lock_init(&dev->rx_lock);
    spin_lock_init(&dev->lock);
    spin_lock_init(&dev->mac_lock);
    spin_lock_init(&dev->con_mon_lock);
    atomic_set(&dev->avg_ampdu_len, 1);
    skb_queue_head_init(&dev->tx_skb_done);
    dev->stat_wq = alloc_workqueue("mt7601u", WQ_UNBOUND, 0);
    if (!dev->stat_wq) {
        ieee80211_free_hw(hw);
        return NULL;
    }
    return dev;
}
#define CHAN2G(_idx, _freq) {            \
    .band = NL80211_BAND_2GHZ,        \
    .center_freq = (_freq),            \
    .hw_value = (_idx),            \
    .max_power = 30,            \
}
static const struct ieee80211_channel mt76_channels_2ghz[] = {
    CHAN2G(1, 2412),
    CHAN2G(2, 2417),
    CHAN2G(3, 2422),
    CHAN2G(4, 2427),
    CHAN2G(5, 2432),
    CHAN2G(6, 2437),
    CHAN2G(7, 2442),
    CHAN2G(8, 2447),
    CHAN2G(9, 2452),
    CHAN2G(10, 2457),
    CHAN2G(11, 2462),
    CHAN2G(12, 2467),
    CHAN2G(13, 2472),
    CHAN2G(14, 2484),
};
#define CCK_RATE(_idx, _rate) {                    \
    .bitrate = _rate,                    \
    .flags = IEEE80211_RATE_SHORT_PREAMBLE,            \
    .hw_value = (MT_PHY_TYPE_CCK << 8) | _idx,        \
    .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (8 + _idx),    \
}
#define OFDM_RATE(_idx, _rate) {                \
    .bitrate = _rate,                    \
    .hw_value = (MT_PHY_TYPE_OFDM << 8) | _idx,        \
    .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | _idx,    \
}
static struct ieee80211_rate mt76_rates[] = {
    CCK_RATE(0, 10),
    CCK_RATE(1, 20),
    CCK_RATE(2, 55),
    CCK_RATE(3, 110),
    OFDM_RATE(0, 60),
    OFDM_RATE(1, 90),
    OFDM_RATE(2, 120),
    OFDM_RATE(3, 180),
    OFDM_RATE(4, 240),
    OFDM_RATE(5, 360),
    OFDM_RATE(6, 480),
    OFDM_RATE(7, 540),
};
static int
mt76_init_sband(struct mt7601u_dev *dev, struct ieee80211_supported_band *sband,
        const struct ieee80211_channel *chan, int n_chan,
        struct ieee80211_rate *rates, int n_rates)
{
    struct ieee80211_sta_ht_cap *ht_cap;
    void *chanlist;
    int size;
    size = n_chan * sizeof(*chan);
    chanlist = devm_kmemdup(dev->dev, chan, size, GFP_KERNEL);
    if (!chanlist)
        return -ENOMEM;
    sband->channels = chanlist;
    sband->n_channels = n_chan;
    sband->bitrates = rates;
    sband->n_bitrates = n_rates;
    ht_cap = &sband->ht_cap;
    ht_cap->ht_supported = true;
    ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
              IEEE80211_HT_CAP_GRN_FLD |
              IEEE80211_HT_CAP_SGI_20 |
              IEEE80211_HT_CAP_SGI_40 |
              (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
    ht_cap->mcs.rx_mask[0] = 0xff;
    ht_cap->mcs.rx_mask[4] = 0x1;
    ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
    ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
    ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_2;
    dev->chandef.chan = &sband->channels[0];
    return 0;
}
static int
mt76_init_sband_2g(struct mt7601u_dev *dev)
{
    dev->sband_2g = devm_kzalloc(dev->dev, sizeof(*dev->sband_2g),
                     GFP_KERNEL);
    dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = dev->sband_2g;
    WARN_ON(dev->ee->reg.start - 1 + dev->ee->reg.num >
        ARRAY_SIZE(mt76_channels_2ghz));
    return mt76_init_sband(dev, dev->sband_2g,
                   &mt76_channels_2ghz[dev->ee->reg.start - 1],
                   dev->ee->reg.num,
                   mt76_rates, ARRAY_SIZE(mt76_rates));
}
int mt7601u_register_device(struct mt7601u_dev *dev)
{
    struct ieee80211_hw *hw = dev->hw;
    struct wiphy *wiphy = hw->wiphy;
    int ret;
    /* Reserve WCID 0 for mcast - thanks to this APs WCID will go to
     * entry no. 1 like it does in the vendor driver.
     */
    dev->wcid_mask[0] |= 1;
    /* init fake wcid for monitor interfaces */
    dev->mon_wcid = devm_kmalloc(dev->dev, sizeof(*dev->mon_wcid),
                     GFP_KERNEL);
    if (!dev->mon_wcid)
        return -ENOMEM;
    dev->mon_wcid->idx = 0xff;
    dev->mon_wcid->hw_key_idx = -1;
    SET_IEEE80211_DEV(hw, dev->dev);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
#define ieee80211_hw_set(hw, flag) (hw)->flags |= IEEE80211_HW_ ## flag;
#endif
    hw->queues = 4;
    ieee80211_hw_set(hw, SIGNAL_DBM);
    ieee80211_hw_set(hw, PS_NULLFUNC_STACK);
    ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES);
    ieee80211_hw_set(hw, AMPDU_AGGREGATION);
#ifdef MAC80211_IS_PATCHED
    ieee80211_hw_set(hw, TX_STATS_EVERY_MPDU);
#endif
    ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
    hw->max_rates = 1;
    hw->max_report_rates = 7;
    hw->max_rate_tries = 1;
    hw->sta_data_size = sizeof(struct mt76_sta);
    hw->vif_data_size = sizeof(struct mt76_vif);
    SET_IEEE80211_PERM_ADDR(hw, dev->macaddr);
    wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
    wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
    ret = mt76_init_sband_2g(dev);
    if (ret)
        return ret;
    INIT_DELAYED_WORK(&dev->mac_work, mt7601u_mac_work);
    INIT_DELAYED_WORK(&dev->stat_work, mt7601u_tx_stat);
    ret = ieee80211_register_hw(hw);
    if (ret)
        return ret;
    mt7601u_init_debugfs(dev);
    return 0;
}
linux-bsp/drivers/mt7601u-sta/initvals.h
New file
@@ -0,0 +1,164 @@
/*
 * (c) Copyright 2002-2010, Ralink Technology, Inc.
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#ifndef __MT7601U_INITVALS_H
#define __MT7601U_INITVALS_H
static const struct mt76_reg_pair bbp_common_vals[] = {
    {  65,    0x2c },
    {  66,    0x38 },
    {  68,    0x0b },
    {  69,    0x12 },
    {  70,    0x0a },
    {  73,    0x10 },
    {  81,    0x37 },
    {  82,    0x62 },
    {  83,    0x6a },
    {  84,    0x99 },
    {  86,    0x00 },
    {  91,    0x04 },
    {  92,    0x00 },
    { 103,    0x00 },
    { 105,    0x05 },
    { 106,    0x35 },
};
static const struct mt76_reg_pair bbp_chip_vals[] = {
    {   1, 0x04 },    {   4, 0x40 },    {  20, 0x06 },    {  31, 0x08 },
    /* CCK Tx Control */
    { 178, 0xff },
    /* AGC/Sync controls */
    {  66, 0x14 },    {  68, 0x8b },    {  69, 0x12 },    {  70, 0x09 },
    {  73, 0x11 },    {  75, 0x60 },    {  76, 0x44 },    {  84, 0x9a },
    {  86, 0x38 },    {  91, 0x07 },    {  92, 0x02 },
    /* Rx Path Controls */
    {  99, 0x50 },    { 101, 0x00 },    { 103, 0xc0 },    { 104, 0x92 },
    { 105, 0x3c },    { 106, 0x03 },    { 128, 0x12 },
    /* Change RXWI content: Gain Report */
    { 142, 0x04 },    { 143, 0x37 },
    /* Change RXWI content: Antenna Report */
    { 142, 0x03 },    { 143, 0x99 },
    /* Calibration Index Register */
    /* CCK Receiver Control */
    { 160, 0xeb },    { 161, 0xc4 },    { 162, 0x77 },    { 163, 0xf9 },
    { 164, 0x88 },    { 165, 0x80 },    { 166, 0xff },    { 167, 0xe4 },
    /* Added AGC controls - these AGC/GLRT registers are accessed
     * through R195 and R196.
     */
    { 195, 0x00 },    { 196, 0x00 },
    { 195, 0x01 },    { 196, 0x04 },
    { 195, 0x02 },    { 196, 0x20 },
    { 195, 0x03 },    { 196, 0x0a },
    { 195, 0x06 },    { 196, 0x16 },
    { 195, 0x07 },    { 196, 0x05 },
    { 195, 0x08 },    { 196, 0x37 },
    { 195, 0x0a },    { 196, 0x15 },
    { 195, 0x0b },    { 196, 0x17 },
    { 195, 0x0c },    { 196, 0x06 },
    { 195, 0x0d },    { 196, 0x09 },
    { 195, 0x0e },    { 196, 0x05 },
    { 195, 0x0f },    { 196, 0x09 },
    { 195, 0x10 },    { 196, 0x20 },
    { 195, 0x20 },    { 196, 0x17 },
    { 195, 0x21 },    { 196, 0x06 },
    { 195, 0x22 },    { 196, 0x09 },
    { 195, 0x23 },    { 196, 0x17 },
    { 195, 0x24 },    { 196, 0x06 },
    { 195, 0x25 },    { 196, 0x09 },
    { 195, 0x26 },    { 196, 0x17 },
    { 195, 0x27 },    { 196, 0x06 },
    { 195, 0x28 },    { 196, 0x09 },
    { 195, 0x29 },    { 196, 0x05 },
    { 195, 0x2a },    { 196, 0x09 },
    { 195, 0x80 },    { 196, 0x8b },
    { 195, 0x81 },    { 196, 0x12 },
    { 195, 0x82 },    { 196, 0x09 },
    { 195, 0x83 },    { 196, 0x17 },
    { 195, 0x84 },    { 196, 0x11 },
    { 195, 0x85 },    { 196, 0x00 },
    { 195, 0x86 },    { 196, 0x00 },
    { 195, 0x87 },    { 196, 0x18 },
    { 195, 0x88 },    { 196, 0x60 },
    { 195, 0x89 },    { 196, 0x44 },
    { 195, 0x8a },    { 196, 0x8b },
    { 195, 0x8b },    { 196, 0x8b },
    { 195, 0x8c },    { 196, 0x8b },
    { 195, 0x8d },    { 196, 0x8b },
    { 195, 0x8e },    { 196, 0x09 },
    { 195, 0x8f },    { 196, 0x09 },
    { 195, 0x90 },    { 196, 0x09 },
    { 195, 0x91 },    { 196, 0x09 },
    { 195, 0x92 },    { 196, 0x11 },
    { 195, 0x93 },    { 196, 0x11 },
    { 195, 0x94 },    { 196, 0x11 },
    { 195, 0x95 },    { 196, 0x11 },
    /* PPAD */
    {  47, 0x80 },    {  60, 0x80 },    { 150, 0xd2 },    { 151, 0x32 },
    { 152, 0x23 },    { 153, 0x41 },    { 154, 0x00 },    { 155, 0x4f },
    { 253, 0x7e },    { 195, 0x30 },    { 196, 0x32 },    { 195, 0x31 },
    { 196, 0x23 },    { 195, 0x32 },    { 196, 0x45 },    { 195, 0x35 },
    { 196, 0x4a },    { 195, 0x36 },    { 196, 0x5a },    { 195, 0x37 },
    { 196, 0x5a },
};
static const struct mt76_reg_pair mac_common_vals[] = {
    { MT_LEGACY_BASIC_RATE,        0x0000013f },
    { MT_HT_BASIC_RATE,        0x00008003 },
    { MT_MAC_SYS_CTRL,        0x00000000 },
    { MT_RX_FILTR_CFG,        0x00017f97 },
    { MT_BKOFF_SLOT_CFG,        0x00000209 },
    { MT_TX_SW_CFG0,        0x00000000 },
    { MT_TX_SW_CFG1,        0x00080606 },
    { MT_TX_LINK_CFG,        0x00001020 },
    { MT_TX_TIMEOUT_CFG,        0x000a2090 },
    { MT_MAX_LEN_CFG,        0x00003fff },
    { MT_PBF_TX_MAX_PCNT,        0x1fbf1f1f },
    { MT_PBF_RX_MAX_PCNT,        0x0000009f },
    { MT_TX_RETRY_CFG,        0x47d01f0f },
    { MT_AUTO_RSP_CFG,        0x00000013 },
    { MT_CCK_PROT_CFG,        0x05740003 },
    { MT_OFDM_PROT_CFG,        0x05740003 },
    { MT_MM40_PROT_CFG,        0x03f44084 },
    { MT_GF20_PROT_CFG,        0x01744004 },
    { MT_GF40_PROT_CFG,        0x03f44084 },
    { MT_MM20_PROT_CFG,        0x01744004 },
    { MT_TXOP_CTRL_CFG,        0x0000583f },
    { MT_TX_RTS_CFG,        0x01092b20 },
    { MT_EXP_ACK_TIME,        0x002400ca },
    { MT_TXOP_HLDR_ET,        0x00000002 },
    { MT_XIFS_TIME_CFG,        0x33a41010 },
    { MT_PWR_PIN_CFG,        0x00000000 },
};
static const struct mt76_reg_pair mac_chip_vals[] = {
    { MT_TSO_CTRL,            0x00006050 },
    { MT_BCN_OFFSET(0),        0x18100800 },
    { MT_BCN_OFFSET(1),        0x38302820 },
    { MT_PBF_SYS_CTRL,        0x00080c00 },
    { MT_PBF_CFG,            0x7f723c1f },
    { MT_FCE_PSE_CTRL,        0x00000001 },
    { MT_PAUSE_ENABLE_CONTROL1,    0x00000000 },
    { MT_TX0_RF_GAIN_CORR,        0x003b0005 },
    { MT_TX0_RF_GAIN_ATTEN,        0x00006900 },
    { MT_TX0_BB_GAIN_ATTEN,        0x00000400 },
    { MT_TX_ALC_VGA3,        0x00060006 },
    { MT_TX_SW_CFG0,        0x00000402 },
    { MT_TX_SW_CFG1,        0x00000000 },
    { MT_TX_SW_CFG2,        0x00000000 },
    { MT_HEADER_TRANS_CTRL_REG,    0x00000000 },
    { MT_FCE_CSO,            0x0000030f },
    { MT_FCE_PARAMETERS,        0x00256f0f },
};
#endif
linux-bsp/drivers/mt7601u-sta/initvals_phy.h
New file
@@ -0,0 +1,291 @@
/*
 * (c) Copyright 2002-2010, Ralink Technology, Inc.
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#ifndef __MT7601U_PHY_INITVALS_H
#define __MT7601U_PHY_INITVALS_H
#define RF_REG_PAIR(bank, reg, value)                \
    { MT_MCU_MEMMAP_RF | (bank) << 16 | (reg), value }
static const struct mt76_reg_pair rf_central[] = {
    /* Bank 0 - for central blocks: BG, PLL, XTAL, LO, ADC/DAC */
    RF_REG_PAIR(0,     0, 0x02),
    RF_REG_PAIR(0,     1, 0x01),
    RF_REG_PAIR(0,     2, 0x11),
    RF_REG_PAIR(0,     3, 0xff),
    RF_REG_PAIR(0,     4, 0x0a),
    RF_REG_PAIR(0,     5, 0x20),
    RF_REG_PAIR(0,     6, 0x00),
    /* B/G */
    RF_REG_PAIR(0,     7, 0x00),
    RF_REG_PAIR(0,     8, 0x00),
    RF_REG_PAIR(0,     9, 0x00),
    RF_REG_PAIR(0,    10, 0x00),
    RF_REG_PAIR(0,    11, 0x21),
    /* XO */
    RF_REG_PAIR(0,    13, 0x00),        /* 40mhz xtal */
    /* RF_REG_PAIR(0,    13, 0x13), */    /* 20mhz xtal */
    RF_REG_PAIR(0,    14, 0x7c),
    RF_REG_PAIR(0,    15, 0x22),
    RF_REG_PAIR(0,    16, 0x80),
    /* PLL */
    RF_REG_PAIR(0,    17, 0x99),
    RF_REG_PAIR(0,    18, 0x99),
    RF_REG_PAIR(0,    19, 0x09),
    RF_REG_PAIR(0,    20, 0x50),
    RF_REG_PAIR(0,    21, 0xb0),
    RF_REG_PAIR(0,    22, 0x00),
    RF_REG_PAIR(0,    23, 0xc5),
    RF_REG_PAIR(0,    24, 0xfc),
    RF_REG_PAIR(0,    25, 0x40),
    RF_REG_PAIR(0,    26, 0x4d),
    RF_REG_PAIR(0,    27, 0x02),
    RF_REG_PAIR(0,    28, 0x72),
    RF_REG_PAIR(0,    29, 0x01),
    RF_REG_PAIR(0,    30, 0x00),
    RF_REG_PAIR(0,    31, 0x00),
    /* test ports */
    RF_REG_PAIR(0,    32, 0x00),
    RF_REG_PAIR(0,    33, 0x00),
    RF_REG_PAIR(0,    34, 0x23),
    RF_REG_PAIR(0,    35, 0x01), /* change setting to reduce spurs */
    RF_REG_PAIR(0,    36, 0x00),
    RF_REG_PAIR(0,    37, 0x00),
    /* ADC/DAC */
    RF_REG_PAIR(0,    38, 0x00),
    RF_REG_PAIR(0,    39, 0x20),
    RF_REG_PAIR(0,    40, 0x00),
    RF_REG_PAIR(0,    41, 0xd0),
    RF_REG_PAIR(0,    42, 0x1b),
    RF_REG_PAIR(0,    43, 0x02),
    RF_REG_PAIR(0,    44, 0x00),
};
static const struct mt76_reg_pair rf_channel[] = {
    RF_REG_PAIR(4,     0, 0x01),
    RF_REG_PAIR(4,     1, 0x00),
    RF_REG_PAIR(4,     2, 0x00),
    RF_REG_PAIR(4,     3, 0x00),
    /* LDO */
    RF_REG_PAIR(4,     4, 0x00),
    RF_REG_PAIR(4,     5, 0x08),
    RF_REG_PAIR(4,     6, 0x00),
    /* RX */
    RF_REG_PAIR(4,     7, 0x5b),
    RF_REG_PAIR(4,     8, 0x52),
    RF_REG_PAIR(4,     9, 0xb6),
    RF_REG_PAIR(4,    10, 0x57),
    RF_REG_PAIR(4,    11, 0x33),
    RF_REG_PAIR(4,    12, 0x22),
    RF_REG_PAIR(4,    13, 0x3d),
    RF_REG_PAIR(4,    14, 0x3e),
    RF_REG_PAIR(4,    15, 0x13),
    RF_REG_PAIR(4,    16, 0x22),
    RF_REG_PAIR(4,    17, 0x23),
    RF_REG_PAIR(4,    18, 0x02),
    RF_REG_PAIR(4,    19, 0xa4),
    RF_REG_PAIR(4,    20, 0x01),
    RF_REG_PAIR(4,    21, 0x12),
    RF_REG_PAIR(4,    22, 0x80),
    RF_REG_PAIR(4,    23, 0xb3),
    RF_REG_PAIR(4,    24, 0x00), /* reserved */
    RF_REG_PAIR(4,    25, 0x00), /* reserved */
    RF_REG_PAIR(4,    26, 0x00), /* reserved */
    RF_REG_PAIR(4,    27, 0x00), /* reserved */
    /* LOGEN */
    RF_REG_PAIR(4,    28, 0x18),
    RF_REG_PAIR(4,    29, 0xee),
    RF_REG_PAIR(4,    30, 0x6b),
    RF_REG_PAIR(4,    31, 0x31),
    RF_REG_PAIR(4,    32, 0x5d),
    RF_REG_PAIR(4,    33, 0x00), /* reserved */
    /* TX */
    RF_REG_PAIR(4,    34, 0x96),
    RF_REG_PAIR(4,    35, 0x55),
    RF_REG_PAIR(4,    36, 0x08),
    RF_REG_PAIR(4,    37, 0xbb),
    RF_REG_PAIR(4,    38, 0xb3),
    RF_REG_PAIR(4,    39, 0xb3),
    RF_REG_PAIR(4,    40, 0x03),
    RF_REG_PAIR(4,    41, 0x00), /* reserved */
    RF_REG_PAIR(4,    42, 0x00), /* reserved */
    RF_REG_PAIR(4,    43, 0xc5),
    RF_REG_PAIR(4,    44, 0xc5),
    RF_REG_PAIR(4,    45, 0xc5),
    RF_REG_PAIR(4,    46, 0x07),
    RF_REG_PAIR(4,    47, 0xa8),
    RF_REG_PAIR(4,    48, 0xef),
    RF_REG_PAIR(4,    49, 0x1a),
    /* PA */
    RF_REG_PAIR(4,    54, 0x07),
    RF_REG_PAIR(4,    55, 0xa7),
    RF_REG_PAIR(4,    56, 0xcc),
    RF_REG_PAIR(4,    57, 0x14),
    RF_REG_PAIR(4,    58, 0x07),
    RF_REG_PAIR(4,    59, 0xa8),
    RF_REG_PAIR(4,    60, 0xd7),
    RF_REG_PAIR(4,    61, 0x10),
    RF_REG_PAIR(4,    62, 0x1c),
    RF_REG_PAIR(4,    63, 0x00), /* reserved */
};
static const struct mt76_reg_pair rf_vga[] = {
    RF_REG_PAIR(5,     0, 0x47),
    RF_REG_PAIR(5,     1, 0x00),
    RF_REG_PAIR(5,     2, 0x00),
    RF_REG_PAIR(5,     3, 0x08),
    RF_REG_PAIR(5,     4, 0x04),
    RF_REG_PAIR(5,     5, 0x20),
    RF_REG_PAIR(5,     6, 0x3a),
    RF_REG_PAIR(5,     7, 0x3a),
    RF_REG_PAIR(5,     8, 0x00),
    RF_REG_PAIR(5,     9, 0x00),
    RF_REG_PAIR(5,    10, 0x10),
    RF_REG_PAIR(5,    11, 0x10),
    RF_REG_PAIR(5,    12, 0x10),
    RF_REG_PAIR(5,    13, 0x10),
    RF_REG_PAIR(5,    14, 0x10),
    RF_REG_PAIR(5,    15, 0x20),
    RF_REG_PAIR(5,    16, 0x22),
    RF_REG_PAIR(5,    17, 0x7c),
    RF_REG_PAIR(5,    18, 0x00),
    RF_REG_PAIR(5,    19, 0x00),
    RF_REG_PAIR(5,    20, 0x00),
    RF_REG_PAIR(5,    21, 0xf1),
    RF_REG_PAIR(5,    22, 0x11),
    RF_REG_PAIR(5,    23, 0x02),
    RF_REG_PAIR(5,    24, 0x41),
    RF_REG_PAIR(5,    25, 0x20),
    RF_REG_PAIR(5,    26, 0x00),
    RF_REG_PAIR(5,    27, 0xd7),
    RF_REG_PAIR(5,    28, 0xa2),
    RF_REG_PAIR(5,    29, 0x20),
    RF_REG_PAIR(5,    30, 0x49),
    RF_REG_PAIR(5,    31, 0x20),
    RF_REG_PAIR(5,    32, 0x04),
    RF_REG_PAIR(5,    33, 0xf1),
    RF_REG_PAIR(5,    34, 0xa1),
    RF_REG_PAIR(5,    35, 0x01),
    RF_REG_PAIR(5,    41, 0x00),
    RF_REG_PAIR(5,    42, 0x00),
    RF_REG_PAIR(5,    43, 0x00),
    RF_REG_PAIR(5,    44, 0x00),
    RF_REG_PAIR(5,    45, 0x00),
    RF_REG_PAIR(5,    46, 0x00),
    RF_REG_PAIR(5,    47, 0x00),
    RF_REG_PAIR(5,    48, 0x00),
    RF_REG_PAIR(5,    49, 0x00),
    RF_REG_PAIR(5,    50, 0x00),
    RF_REG_PAIR(5,    51, 0x00),
    RF_REG_PAIR(5,    52, 0x00),
    RF_REG_PAIR(5,    53, 0x00),
    RF_REG_PAIR(5,    54, 0x00),
    RF_REG_PAIR(5,    55, 0x00),
    RF_REG_PAIR(5,    56, 0x00),
    RF_REG_PAIR(5,    57, 0x00),
    RF_REG_PAIR(5,    58, 0x31),
    RF_REG_PAIR(5,    59, 0x31),
    RF_REG_PAIR(5,    60, 0x0a),
    RF_REG_PAIR(5,    61, 0x02),
    RF_REG_PAIR(5,    62, 0x00),
    RF_REG_PAIR(5,    63, 0x00),
};
/* TODO: BBP178 is set to 0xff for "CCK CH14 OBW" which overrides the settings
 *     from channel switching. Seems stupid at best.
 */
static const struct mt76_reg_pair bbp_high_temp[] = {
    {  75, 0x60 },
    {  92, 0x02 },
    { 178, 0xff }, /* For CCK CH14 OBW */
    { 195, 0x88 }, { 196, 0x60 },
}, bbp_high_temp_bw20[] = {
    {  69, 0x12 },
    {  91, 0x07 },
    { 195, 0x23 }, { 196, 0x17 },
    { 195, 0x24 }, { 196, 0x06 },
    { 195, 0x81 }, { 196, 0x12 },
    { 195, 0x83 }, { 196, 0x17 },
}, bbp_high_temp_bw40[] = {
    {  69, 0x15 },
    {  91, 0x04 },
    { 195, 0x23 }, { 196, 0x12 },
    { 195, 0x24 }, { 196, 0x08 },
    { 195, 0x81 }, { 196, 0x15 },
    { 195, 0x83 }, { 196, 0x16 },
}, bbp_low_temp[] = {
    { 178, 0xff }, /* For CCK CH14 OBW */
}, bbp_low_temp_bw20[] = {
    {  69, 0x12 },
    {  75, 0x5e },
    {  91, 0x07 },
    {  92, 0x02 },
    { 195, 0x23 }, { 196, 0x17 },
    { 195, 0x24 }, { 196, 0x06 },
    { 195, 0x81 }, { 196, 0x12 },
    { 195, 0x83 }, { 196, 0x17 },
    { 195, 0x88 }, { 196, 0x5e },
}, bbp_low_temp_bw40[] = {
    {  69, 0x15 },
    {  75, 0x5c },
    {  91, 0x04 },
    {  92, 0x03 },
    { 195, 0x23 }, { 196, 0x10 },
    { 195, 0x24 }, { 196, 0x08 },
    { 195, 0x81 }, { 196, 0x15 },
    { 195, 0x83 }, { 196, 0x16 },
    { 195, 0x88 }, { 196, 0x5b },
}, bbp_normal_temp[] = {
    {  75, 0x60 },
    {  92, 0x02 },
    { 178, 0xff }, /* For CCK CH14 OBW */
    { 195, 0x88 }, { 196, 0x60 },
}, bbp_normal_temp_bw20[] = {
    {  69, 0x12 },
    {  91, 0x07 },
    { 195, 0x23 }, { 196, 0x17 },
    { 195, 0x24 }, { 196, 0x06 },
    { 195, 0x81 }, { 196, 0x12 },
    { 195, 0x83 }, { 196, 0x17 },
}, bbp_normal_temp_bw40[] = {
    {  69, 0x15 },
    {  91, 0x04 },
    { 195, 0x23 }, { 196, 0x12 },
    { 195, 0x24 }, { 196, 0x08 },
    { 195, 0x81 }, { 196, 0x15 },
    { 195, 0x83 }, { 196, 0x16 },
};
#define BBP_TABLE(arr) { arr, ARRAY_SIZE(arr), }
static const struct reg_table {
    const struct mt76_reg_pair *regs;
    size_t n;
} bbp_mode_table[3][3] = {
    {
        BBP_TABLE(bbp_normal_temp_bw20),
        BBP_TABLE(bbp_normal_temp_bw40),
        BBP_TABLE(bbp_normal_temp),
    }, {
        BBP_TABLE(bbp_high_temp_bw20),
        BBP_TABLE(bbp_high_temp_bw40),
        BBP_TABLE(bbp_high_temp),
    }, {
        BBP_TABLE(bbp_low_temp_bw20),
        BBP_TABLE(bbp_low_temp_bw40),
        BBP_TABLE(bbp_low_temp),
    }
};
#endif
linux-bsp/drivers/mt7601u-sta/mac.c
New file
@@ -0,0 +1,581 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#include "mt7601u.h"
#include "trace.h"
#include <linux/etherdevice.h>
static void
mt76_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate)
{
    u8 idx = MT76_GET(MT_TXWI_RATE_MCS, rate);
    txrate->idx = 0;
    txrate->flags = 0;
    txrate->count = 1;
    switch (MT76_GET(MT_TXWI_RATE_PHY_MODE, rate)) {
    case MT_PHY_TYPE_OFDM:
        txrate->idx = idx + 4;
        return;
    case MT_PHY_TYPE_CCK:
        if (idx >= 8)
            idx -= 8;
        txrate->idx = idx;
        return;
    case MT_PHY_TYPE_HT_GF:
        txrate->flags |= IEEE80211_TX_RC_GREEN_FIELD;
        /* fall through */
    case MT_PHY_TYPE_HT:
        txrate->flags |= IEEE80211_TX_RC_MCS;
        txrate->idx = idx;
        break;
    default:
        WARN_ON(1);
        return;
    }
    if (MT76_GET(MT_TXWI_RATE_BW, rate) == MT_PHY_BW_40)
        txrate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
    if (rate & MT_TXWI_RATE_SGI)
        txrate->flags |= IEEE80211_TX_RC_SHORT_GI;
}
static void
mt76_mac_fill_tx_status(struct mt7601u_dev *dev, struct ieee80211_tx_info *info,
            struct mt76_tx_status *st)
{
    struct ieee80211_tx_rate *rate = info->status.rates;
    int cur_idx, last_rate;
    int i;
    last_rate = min_t(int, st->retry, IEEE80211_TX_MAX_RATES - 1);
    mt76_mac_process_tx_rate(&rate[last_rate], st->rate);
    if (last_rate < IEEE80211_TX_MAX_RATES - 1)
        rate[last_rate + 1].idx = -1;
    cur_idx = rate[last_rate].idx + st->retry;
    for (i = 0; i <= last_rate; i++) {
        rate[i].flags = rate[last_rate].flags;
        rate[i].idx = max_t(int, 0, cur_idx - i);
        rate[i].count = 1;
    }
    if (last_rate > 0)
        rate[last_rate - 1].count = st->retry + 1 - last_rate;
#ifdef MAC80211_IS_PATCHED
    info->status.ampdu_len = atomic_read(&dev->avg_ampdu_len);
#else
    info->status.ampdu_len = 1;
#endif
    info->status.ampdu_ack_len = st->success;
    if (st->is_probe)
        info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
    if (st->aggr)
        info->flags |= IEEE80211_TX_CTL_AMPDU |
                   IEEE80211_TX_STAT_AMPDU;
    if (!st->ack_req)
        info->flags |= IEEE80211_TX_CTL_NO_ACK;
    else if (st->success)
        info->flags |= IEEE80211_TX_STAT_ACK;
}
u16 mt76_mac_tx_rate_val(struct mt7601u_dev *dev,
             const struct ieee80211_tx_rate *rate, u8 *nss_val)
{
    u16 rateval;
    u8 phy, rate_idx;
    u8 nss = 1;
    u8 bw = 0;
    if (rate->flags & IEEE80211_TX_RC_MCS) {
        rate_idx = rate->idx;
        nss = 1 + (rate->idx >> 3);
        phy = MT_PHY_TYPE_HT;
        if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD)
            phy = MT_PHY_TYPE_HT_GF;
        if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
            bw = 1;
    } else {
        const struct ieee80211_rate *r;
        int band = dev->chandef.chan->band;
        u16 val;
        r = &dev->hw->wiphy->bands[band]->bitrates[rate->idx];
        if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
            val = r->hw_value_short;
        else
            val = r->hw_value;
        phy = val >> 8;
        rate_idx = val & 0xff;
        bw = 0;
    }
    rateval = MT76_SET(MT_RXWI_RATE_MCS, rate_idx);
    rateval |= MT76_SET(MT_RXWI_RATE_PHY, phy);
    rateval |= MT76_SET(MT_RXWI_RATE_BW, bw);
    if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
        rateval |= MT_RXWI_RATE_SGI;
    *nss_val = nss;
    return rateval;
}
void mt76_mac_wcid_set_rate(struct mt7601u_dev *dev, struct mt76_wcid *wcid,
                const struct ieee80211_tx_rate *rate)
{
    unsigned long flags;
    spin_lock_irqsave(&dev->lock, flags);
    wcid->tx_rate = mt76_mac_tx_rate_val(dev, rate, &wcid->tx_rate_nss);
    wcid->tx_rate_set = true;
    spin_unlock_irqrestore(&dev->lock, flags);
}
struct mt76_tx_status mt7601u_mac_fetch_tx_status(struct mt7601u_dev *dev)
{
    struct mt76_tx_status stat = {};
    u32 val;
    val = mt7601u_rr(dev, MT_TX_STAT_FIFO);
    stat.valid = !!(val & MT_TX_STAT_FIFO_VALID);
    stat.success = !!(val & MT_TX_STAT_FIFO_SUCCESS);
    stat.aggr = !!(val & MT_TX_STAT_FIFO_AGGR);
    stat.ack_req = !!(val & MT_TX_STAT_FIFO_ACKREQ);
    stat.pktid = MT76_GET(MT_TX_STAT_FIFO_PID_TYPE, val);
    stat.wcid = MT76_GET(MT_TX_STAT_FIFO_WCID, val);
    stat.rate = MT76_GET(MT_TX_STAT_FIFO_RATE, val);
    return stat;
}
void mt76_send_tx_status(struct mt7601u_dev *dev, struct mt76_tx_status *stat)
{
    struct ieee80211_tx_info info = {};
    struct ieee80211_sta *sta = NULL;
    struct mt76_wcid *wcid = NULL;
    void *msta;
    rcu_read_lock();
    if (stat->wcid < ARRAY_SIZE(dev->wcid))
        wcid = rcu_dereference(dev->wcid[stat->wcid]);
    if (wcid) {
        msta = container_of(wcid, struct mt76_sta, wcid);
        sta = container_of(msta, struct ieee80211_sta,
                   drv_priv);
    }
    mt76_mac_fill_tx_status(dev, &info, stat);
    spin_lock_bh(&dev->mac_lock);
    ieee80211_tx_status_noskb(dev->hw, sta, &info);
    spin_unlock_bh(&dev->mac_lock);
    rcu_read_unlock();
}
void mt7601u_mac_set_protection(struct mt7601u_dev *dev, bool legacy_prot,
                int ht_mode)
{
    int mode = ht_mode & IEEE80211_HT_OP_MODE_PROTECTION;
    bool non_gf = !!(ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
    u32 prot[6];
    bool ht_rts[4] = {};
    int i;
    prot[0] = MT_PROT_NAV_SHORT |
          MT_PROT_TXOP_ALLOW_ALL |
          MT_PROT_RTS_THR_EN;
    prot[1] = prot[0];
    if (legacy_prot)
        prot[1] |= MT_PROT_CTRL_CTS2SELF;
    prot[2] = prot[4] = MT_PROT_NAV_SHORT | MT_PROT_TXOP_ALLOW_BW20;
    prot[3] = prot[5] = MT_PROT_NAV_SHORT | MT_PROT_TXOP_ALLOW_ALL;
    if (legacy_prot) {
        prot[2] |= MT_PROT_RATE_CCK_11;
        prot[3] |= MT_PROT_RATE_CCK_11;
        prot[4] |= MT_PROT_RATE_CCK_11;
        prot[5] |= MT_PROT_RATE_CCK_11;
    } else {
        prot[2] |= MT_PROT_RATE_OFDM_24;
        prot[3] |= MT_PROT_RATE_DUP_OFDM_24;
        prot[4] |= MT_PROT_RATE_OFDM_24;
        prot[5] |= MT_PROT_RATE_DUP_OFDM_24;
    }
    switch (mode) {
    case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
        break;
    case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
        ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true;
        break;
    case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
        ht_rts[1] = ht_rts[3] = true;
        break;
    case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
        ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true;
        break;
    }
    if (non_gf)
        ht_rts[2] = ht_rts[3] = true;
    for (i = 0; i < 4; i++)
        if (ht_rts[i])
            prot[i + 2] |= MT_PROT_CTRL_RTS_CTS;
    for (i = 0; i < 6; i++)
        mt7601u_wr(dev, MT_CCK_PROT_CFG + i * 4, prot[i]);
}
void mt7601u_mac_set_short_preamble(struct mt7601u_dev *dev, bool short_preamb)
{
    if (short_preamb)
        mt76_set(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT);
    else
        mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT);
}
void mt7601u_mac_config_tsf(struct mt7601u_dev *dev, bool enable, int interval)
{
    u32 val = mt7601u_rr(dev, MT_BEACON_TIME_CFG);
    val &= ~(MT_BEACON_TIME_CFG_TIMER_EN |
         MT_BEACON_TIME_CFG_SYNC_MODE |
         MT_BEACON_TIME_CFG_TBTT_EN);
    if (!enable) {
        mt7601u_wr(dev, MT_BEACON_TIME_CFG, val);
        return;
    }
    val &= ~MT_BEACON_TIME_CFG_INTVAL;
    val |= MT76_SET(MT_BEACON_TIME_CFG_INTVAL, interval << 4) |
        MT_BEACON_TIME_CFG_TIMER_EN |
        MT_BEACON_TIME_CFG_SYNC_MODE |
        MT_BEACON_TIME_CFG_TBTT_EN;
}
static void mt7601u_check_mac_err(struct mt7601u_dev *dev)
{
    u32 val = mt7601u_rr(dev, 0x10f4);
    if (!(val & BIT(29)) || !(val & (BIT(7) | BIT(5))))
        return;
    dev_err(dev->dev, "Error: MAC specific condition occurred\n");
    mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
    udelay(10);
    mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
}
void mt7601u_mac_work(struct work_struct *work)
{
    struct mt7601u_dev *dev = container_of(work, struct mt7601u_dev,
                           mac_work.work);
    struct {
        u32 addr_base;
        u32 span;
        u64 *stat_base;
    } spans[] = {
        { MT_RX_STA_CNT0,    3,    dev->stats.rx_stat },
        { MT_TX_STA_CNT0,    3,    dev->stats.tx_stat },
        { MT_TX_AGG_STAT,    1,    dev->stats.aggr_stat },
        { MT_MPDU_DENSITY_CNT,    1,    dev->stats.zero_len_del },
        { MT_TX_AGG_CNT_BASE0,    8,    &dev->stats.aggr_n[0] },
        { MT_TX_AGG_CNT_BASE1,    8,    &dev->stats.aggr_n[16] },
    };
    u32 sum, n;
    int i, j, k;
    /* Note: using MCU_RANDOM_READ is actually slower then reading all the
     *     registers by hand.  MCU takes ca. 20ms to complete read of 24
     *     registers while reading them one by one will takes roughly
     *     24*200us =~ 5ms.
     */
    k = 0;
    n = 0;
    sum = 0;
    for (i = 0; i < ARRAY_SIZE(spans); i++)
        for (j = 0; j < spans[i].span; j++) {
            u32 val = mt7601u_rr(dev, spans[i].addr_base + j * 4);
            spans[i].stat_base[j * 2] += val & 0xffff;
            spans[i].stat_base[j * 2 + 1] += val >> 16;
            /* Calculate average AMPDU length */
            if (spans[i].addr_base != MT_TX_AGG_CNT_BASE0 &&
                spans[i].addr_base != MT_TX_AGG_CNT_BASE1)
                continue;
            n += (val >> 16) + (val & 0xffff);
            sum += (val & 0xffff) * (1 + k * 2) +
                (val >> 16) * (2 + k * 2);
            k++;
        }
    atomic_set(&dev->avg_ampdu_len, n ? DIV_ROUND_CLOSEST(sum, n) : 1);
    mt7601u_check_mac_err(dev);
    ieee80211_queue_delayed_work(dev->hw, &dev->mac_work, 10 * HZ);
}
void
mt7601u_mac_wcid_setup(struct mt7601u_dev *dev, u8 idx, u8 vif_idx, u8 *mac)
{
    u8 zmac[ETH_ALEN] = {};
    u32 attr;
    attr = MT76_SET(MT_WCID_ATTR_BSS_IDX, vif_idx & 7) |
           MT76_SET(MT_WCID_ATTR_BSS_IDX_EXT, !!(vif_idx & 8));
    mt76_wr(dev, MT_WCID_ATTR(idx), attr);
    if (mac)
        memcpy(zmac, mac, sizeof(zmac));
    mt7601u_addr_wr(dev, MT_WCID_ADDR(idx), zmac);
}
void mt7601u_mac_set_ampdu_factor(struct mt7601u_dev *dev)
{
    struct ieee80211_sta *sta;
    struct mt76_wcid *wcid;
    void *msta;
    u8 min_factor = 3;
    int i;
    rcu_read_lock();
    for (i = 0; i < ARRAY_SIZE(dev->wcid); i++) {
        wcid = rcu_dereference(dev->wcid[i]);
        if (!wcid)
            continue;
        msta = container_of(wcid, struct mt76_sta, wcid);
        sta = container_of(msta, struct ieee80211_sta, drv_priv);
        min_factor = min(min_factor, sta->ht_cap.ampdu_factor);
    }
    rcu_read_unlock();
    mt7601u_wr(dev, MT_MAX_LEN_CFG, 0xa0fff |
           MT76_SET(MT_MAX_LEN_CFG_AMPDU, min_factor));
}
static void
mt76_mac_process_rate(struct ieee80211_rx_status *status, u16 rate)
{
    u8 idx = MT76_GET(MT_RXWI_RATE_MCS, rate);
    switch (MT76_GET(MT_RXWI_RATE_PHY, rate)) {
    case MT_PHY_TYPE_OFDM:
        if (WARN_ON(idx >= 8))
            idx = 0;
        idx += 4;
        status->rate_idx = idx;
        return;
    case MT_PHY_TYPE_CCK:
        if (idx >= 8) {
            idx -= 8;
            status->flag |= RX_FLAG_SHORTPRE;
        }
        if (WARN_ON(idx >= 4))
            idx = 0;
        status->rate_idx = idx;
        return;
    case MT_PHY_TYPE_HT_GF:
        status->flag |= RX_FLAG_HT_GF;
        /* fall through */
    case MT_PHY_TYPE_HT:
        status->flag |= RX_FLAG_HT;
        status->rate_idx = idx;
        break;
    default:
        WARN_ON(1);
        return;
    }
    if (rate & MT_RXWI_RATE_SGI)
        status->flag |= RX_FLAG_SHORT_GI;
    if (rate & MT_RXWI_RATE_STBC)
        status->flag |= 1 << RX_FLAG_STBC_SHIFT;
    if (rate & MT_RXWI_RATE_BW)
        status->flag |= RX_FLAG_40MHZ;
}
static void
mt7601u_rx_monitor_beacon(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
              u16 rate, int rssi)
{
    dev->bcn_freq_off = rxwi->freq_off;
    dev->bcn_phy_mode = MT76_GET(MT_RXWI_RATE_PHY, rate);
    dev->avg_rssi = (dev->avg_rssi * 15) / 16 + (rssi << 8);
}
static int
mt7601u_rx_is_our_beacon(struct mt7601u_dev *dev, u8 *data)
{
    struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data;
    return ieee80211_is_beacon(hdr->frame_control) &&
        ether_addr_equal(hdr->addr2, dev->ap_bssid);
}
u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
            u8 *data, void *rxi)
{
    struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
    struct mt7601u_rxwi *rxwi = rxi;
    u32 len, ctl = le32_to_cpu(rxwi->ctl);
    u16 rate = le16_to_cpu(rxwi->rate);
    int rssi;
    len = MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
    if (len < 10)
        return 0;
    if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) {
        status->flag |= RX_FLAG_DECRYPTED;
        status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
    }
    status->chains = BIT(0);
    rssi = mt7601u_phy_get_rssi(dev, rxwi, rate);
    status->chain_signal[0] = status->signal = rssi;
    status->freq = dev->chandef.chan->center_freq;
    status->band = dev->chandef.chan->band;
    mt76_mac_process_rate(status, rate);
    spin_lock_bh(&dev->con_mon_lock);
    if (mt7601u_rx_is_our_beacon(dev, data))
        mt7601u_rx_monitor_beacon(dev, rxwi, rate, rssi);
    else if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_U2M))
        dev->avg_rssi = (dev->avg_rssi * 15) / 16 + (rssi << 8);
    spin_unlock_bh(&dev->con_mon_lock);
    return len;
}
static enum mt76_cipher_type
mt76_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data)
{
    memset(key_data, 0, 32);
    if (!key)
        return MT_CIPHER_NONE;
    if (key->keylen > 32)
        return MT_CIPHER_NONE;
    memcpy(key_data, key->key, key->keylen);
    switch (key->cipher) {
    case WLAN_CIPHER_SUITE_WEP40:
        return MT_CIPHER_WEP40;
    case WLAN_CIPHER_SUITE_WEP104:
        return MT_CIPHER_WEP104;
    case WLAN_CIPHER_SUITE_TKIP:
        return MT_CIPHER_TKIP;
    case WLAN_CIPHER_SUITE_CCMP:
        return MT_CIPHER_AES_CCMP;
    default:
        return MT_CIPHER_NONE;
    }
}
int mt76_mac_wcid_set_key(struct mt7601u_dev *dev, u8 idx,
              struct ieee80211_key_conf *key)
{
    enum mt76_cipher_type cipher;
    u8 key_data[32];
    u8 iv_data[8];
    u32 val;
    cipher = mt76_mac_get_key_info(key, key_data);
    if (cipher == MT_CIPHER_NONE && key)
        return -EINVAL;
    trace_set_key(dev, idx);
    mt7601u_wr_copy(dev, MT_WCID_KEY(idx), key_data, sizeof(key_data));
    memset(iv_data, 0, sizeof(iv_data));
    if (key) {
        iv_data[3] = key->keyidx << 6;
        if (cipher >= MT_CIPHER_TKIP) {
            /* Note: start with 1 to comply with spec,
             *     (see comment on common/cmm_wpa.c:4291).
             */
            iv_data[0] |= 1;
            iv_data[3] |= 0x20;
        }
    }
    mt7601u_wr_copy(dev, MT_WCID_IV(idx), iv_data, sizeof(iv_data));
    val = mt7601u_rr(dev, MT_WCID_ATTR(idx));
    val &= ~MT_WCID_ATTR_PKEY_MODE & ~MT_WCID_ATTR_PKEY_MODE_EXT;
    val |= MT76_SET(MT_WCID_ATTR_PKEY_MODE, cipher & 7) |
           MT76_SET(MT_WCID_ATTR_PKEY_MODE_EXT, cipher >> 3);
    val &= ~MT_WCID_ATTR_PAIRWISE;
    val |= MT_WCID_ATTR_PAIRWISE *
        !!(key && key->flags & IEEE80211_KEY_FLAG_PAIRWISE);
    mt7601u_wr(dev, MT_WCID_ATTR(idx), val);
    return 0;
}
int mt76_mac_shared_key_setup(struct mt7601u_dev *dev, u8 vif_idx, u8 key_idx,
                  struct ieee80211_key_conf *key)
{
    enum mt76_cipher_type cipher;
    u8 key_data[32];
    u32 val;
    cipher = mt76_mac_get_key_info(key, key_data);
    if (cipher == MT_CIPHER_NONE && key)
        return -EINVAL;
    trace_set_shared_key(dev, vif_idx, key_idx);
    mt7601u_wr_copy(dev, MT_SKEY(vif_idx, key_idx),
            key_data, sizeof(key_data));
    val = mt76_rr(dev, MT_SKEY_MODE(vif_idx));
    val &= ~(MT_SKEY_MODE_MASK << MT_SKEY_MODE_SHIFT(vif_idx, key_idx));
    val |= cipher << MT_SKEY_MODE_SHIFT(vif_idx, key_idx);
    mt76_wr(dev, MT_SKEY_MODE(vif_idx), val);
    return 0;
}
linux-bsp/drivers/mt7601u-sta/mac.h
New file
@@ -0,0 +1,178 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#ifndef __MT76_MAC_H
#define __MT76_MAC_H
struct mt76_tx_status {
    u8 valid:1;
    u8 success:1;
    u8 aggr:1;
    u8 ack_req:1;
    u8 is_probe:1;
    u8 wcid;
    u8 pktid;
    u8 retry;
    u16 rate;
} __packed __aligned(2);
/* Note: values in original "RSSI" and "SNR" fields are not actually what they
 *     are called for MT7601U, names used by this driver are educated guesses
 *     (see vendor mac/ral_omac.c).
 */
struct mt7601u_rxwi {
    __le32 rxinfo;
    __le32 ctl;
    __le16 frag_sn;
    __le16 rate;
    u8 unknown;
    u8 zero[3];
    u8 snr;
    u8 ant;
    u8 gain;
    u8 freq_off;
    __le32 resv2;
    __le32 expert_ant;
} __packed __aligned(4);
#define MT_RXINFO_BA            BIT(0)
#define MT_RXINFO_DATA            BIT(1)
#define MT_RXINFO_NULL            BIT(2)
#define MT_RXINFO_FRAG            BIT(3)
#define MT_RXINFO_U2M            BIT(4)
#define MT_RXINFO_MULTICAST        BIT(5)
#define MT_RXINFO_BROADCAST        BIT(6)
#define MT_RXINFO_MYBSS            BIT(7)
#define MT_RXINFO_CRCERR        BIT(8)
#define MT_RXINFO_ICVERR        BIT(9)
#define MT_RXINFO_MICERR        BIT(10)
#define MT_RXINFO_AMSDU            BIT(11)
#define MT_RXINFO_HTC            BIT(12)
#define MT_RXINFO_RSSI            BIT(13)
#define MT_RXINFO_L2PAD            BIT(14)
#define MT_RXINFO_AMPDU            BIT(15)
#define MT_RXINFO_DECRYPT        BIT(16)
#define MT_RXINFO_BSSIDX3        BIT(17)
#define MT_RXINFO_WAPI_KEY        BIT(18)
#define MT_RXINFO_PN_LEN        GENMASK(21, 19)
#define MT_RXINFO_SW_PKT_80211        BIT(22)
#define MT_RXINFO_TCP_SUM_BYPASS    BIT(28)
#define MT_RXINFO_IP_SUM_BYPASS        BIT(29)
#define MT_RXINFO_TCP_SUM_ERR        BIT(30)
#define MT_RXINFO_IP_SUM_ERR        BIT(31)
#define MT_RXWI_CTL_WCID        GENMASK(7, 0)
#define MT_RXWI_CTL_KEY_IDX        GENMASK(9, 8)
#define MT_RXWI_CTL_BSS_IDX        GENMASK(12, 10)
#define MT_RXWI_CTL_UDF            GENMASK(15, 13)
#define MT_RXWI_CTL_MPDU_LEN        GENMASK(27, 16)
#define MT_RXWI_CTL_TID            GENMASK(31, 28)
#define MT_RXWI_FRAG            GENMASK(3, 0)
#define MT_RXWI_SN            GENMASK(15, 4)
#define MT_RXWI_RATE_MCS        GENMASK(6, 0)
#define MT_RXWI_RATE_BW            BIT(7)
#define MT_RXWI_RATE_SGI        BIT(8)
#define MT_RXWI_RATE_STBC        GENMASK(10, 9)
#define MT_RXWI_RATE_ETXBF        BIT(11)
#define MT_RXWI_RATE_SND        BIT(12)
#define MT_RXWI_RATE_ITXBF        BIT(13)
#define MT_RXWI_RATE_PHY        GENMASK(15, 14)
#define MT_RXWI_GAIN_RSSI_VAL        GENMASK(5, 0)
#define MT_RXWI_GAIN_RSSI_LNA_ID    GENMASK(7, 6)
#define MT_RXWI_ANT_AUX_LNA        BIT(7)
#define MT_RXWI_EANT_ENC_ANT_ID        GENMASK(7, 0)
enum mt76_phy_type {
    MT_PHY_TYPE_CCK,
    MT_PHY_TYPE_OFDM,
    MT_PHY_TYPE_HT,
    MT_PHY_TYPE_HT_GF,
};
enum mt76_phy_bandwidth {
    MT_PHY_BW_20,
    MT_PHY_BW_40,
};
struct mt76_txwi {
    __le16 flags;
    __le16 rate_ctl;
    u8 ack_ctl;
    u8 wcid;
    __le16 len_ctl;
    __le32 iv;
    __le32 eiv;
    u8 aid;
    u8 txstream;
    __le16 ctl;
} __packed __aligned(4);
#define MT_TXWI_FLAGS_FRAG        BIT(0)
#define MT_TXWI_FLAGS_MMPS        BIT(1)
#define MT_TXWI_FLAGS_CFACK        BIT(2)
#define MT_TXWI_FLAGS_TS        BIT(3)
#define MT_TXWI_FLAGS_AMPDU        BIT(4)
#define MT_TXWI_FLAGS_MPDU_DENSITY    GENMASK(7, 5)
#define MT_TXWI_FLAGS_TXOP        GENMASK(9, 8)
#define MT_TXWI_FLAGS_CWMIN        GENMASK(12, 10)
#define MT_TXWI_FLAGS_NO_RATE_FALLBACK    BIT(13)
#define MT_TXWI_FLAGS_TX_RPT        BIT(14)
#define MT_TXWI_FLAGS_TX_RATE_LUT    BIT(15)
#define MT_TXWI_RATE_MCS        GENMASK(6, 0)
#define MT_TXWI_RATE_BW            BIT(7)
#define MT_TXWI_RATE_SGI        BIT(8)
#define MT_TXWI_RATE_STBC        GENMASK(10, 9)
#define MT_TXWI_RATE_PHY_MODE        GENMASK(15, 14)
#define MT_TXWI_ACK_CTL_REQ        BIT(0)
#define MT_TXWI_ACK_CTL_NSEQ        BIT(1)
#define MT_TXWI_ACK_CTL_BA_WINDOW    GENMASK(7, 2)
#define MT_TXWI_LEN_BYTE_CNT        GENMASK(11, 0)
#define MT_TXWI_LEN_PKTID        GENMASK(15, 12)
#define MT_TXWI_CTL_TX_POWER_ADJ    GENMASK(3, 0)
#define MT_TXWI_CTL_CHAN_CHECK_PKT    BIT(4)
#define MT_TXWI_CTL_PIFS_REV        BIT(6)
u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
            u8 *data, void *rxi);
int mt76_mac_wcid_set_key(struct mt7601u_dev *dev, u8 idx,
              struct ieee80211_key_conf *key);
void mt76_mac_wcid_set_rate(struct mt7601u_dev *dev, struct mt76_wcid *wcid,
                const struct ieee80211_tx_rate *rate);
int mt76_mac_shared_key_setup(struct mt7601u_dev *dev, u8 vif_idx, u8 key_idx,
                  struct ieee80211_key_conf *key);
u16 mt76_mac_tx_rate_val(struct mt7601u_dev *dev,
             const struct ieee80211_tx_rate *rate, u8 *nss_val);
struct mt76_tx_status
mt7601u_mac_fetch_tx_status(struct mt7601u_dev *dev);
void mt76_send_tx_status(struct mt7601u_dev *dev, struct mt76_tx_status *stat);
#endif
linux-bsp/drivers/mt7601u-sta/main.c
New file
@@ -0,0 +1,432 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#include "mt7601u.h"
#include "mac.h"
#include <linux/etherdevice.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
#error Your kernel is too old, please upgrade to at least 3.19
#endif
static int mt7601u_start(struct ieee80211_hw *hw)
{
    struct mt7601u_dev *dev = hw->priv;
    int ret;
    mutex_lock(&dev->mutex);
    ret = mt7601u_mac_start(dev);
    if (ret)
        goto out;
    ieee80211_queue_delayed_work(dev->hw, &dev->mac_work,
                     MT_CALIBRATE_INTERVAL);
    ieee80211_queue_delayed_work(dev->hw, &dev->cal_work,
                     MT_CALIBRATE_INTERVAL);
out:
    mutex_unlock(&dev->mutex);
    return ret;
}
static void mt7601u_stop(struct ieee80211_hw *hw)
{
    struct mt7601u_dev *dev = hw->priv;
    mutex_lock(&dev->mutex);
    cancel_delayed_work_sync(&dev->cal_work);
    cancel_delayed_work_sync(&dev->mac_work);
    mt7601u_mac_stop(dev);
    mutex_unlock(&dev->mutex);
}
static int mt7601u_add_interface(struct ieee80211_hw *hw,
                 struct ieee80211_vif *vif)
{
    struct mt7601u_dev *dev = hw->priv;
    struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
    unsigned int idx = 0;
    unsigned int wcid = GROUP_WCID(idx);
    /* Note: for AP do the AP-STA things mt76 does:
     *    - beacon offsets
     *    - do mac address tricks
     *    - shift vif idx
     */
    mvif->idx = idx;
    if (dev->wcid_mask[wcid / BITS_PER_LONG] & BIT(wcid % BITS_PER_LONG))
        return -ENOSPC;
    dev->wcid_mask[wcid / BITS_PER_LONG] |= BIT(wcid % BITS_PER_LONG);
    mvif->group_wcid.idx = wcid;
    mvif->group_wcid.hw_key_idx = -1;
    return 0;
}
static void mt7601u_remove_interface(struct ieee80211_hw *hw,
                     struct ieee80211_vif *vif)
{
    struct mt7601u_dev *dev = hw->priv;
    struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
    unsigned int wcid = mvif->group_wcid.idx;
    dev->wcid_mask[wcid / BITS_PER_LONG] &= ~BIT(wcid % BITS_PER_LONG);
}
static int mt7601u_config(struct ieee80211_hw *hw, u32 changed)
{
    struct mt7601u_dev *dev = hw->priv;
    int ret = 0;
    mutex_lock(&dev->mutex);
    if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
        ieee80211_stop_queues(hw);
        ret = mt7601u_phy_set_channel(dev, &hw->conf.chandef);
        ieee80211_wake_queues(hw);
    }
    mutex_unlock(&dev->mutex);
    return ret;
}
static void
mt76_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
              unsigned int *total_flags, u64 multicast)
{
    struct mt7601u_dev *dev = hw->priv;
    u32 flags = 0;
#define MT76_FILTER(_flag, _hw) do { \
        flags |= *total_flags & FIF_##_flag;            \
        dev->rxfilter &= ~(_hw);                \
        dev->rxfilter |= !(flags & FIF_##_flag) * (_hw);    \
    } while (0)
    mutex_lock(&dev->mutex);
    dev->rxfilter &= ~MT_RX_FILTR_CFG_OTHER_BSS;
    MT76_FILTER(OTHER_BSS, MT_RX_FILTR_CFG_PROMISC);
    MT76_FILTER(FCSFAIL, MT_RX_FILTR_CFG_CRC_ERR);
    MT76_FILTER(PLCPFAIL, MT_RX_FILTR_CFG_PHY_ERR);
    MT76_FILTER(CONTROL, MT_RX_FILTR_CFG_ACK |
                 MT_RX_FILTR_CFG_CTS |
                 MT_RX_FILTR_CFG_CFEND |
                 MT_RX_FILTR_CFG_CFACK |
                 MT_RX_FILTR_CFG_BA |
                 MT_RX_FILTR_CFG_CTRL_RSV);
    MT76_FILTER(PSPOLL, MT_RX_FILTR_CFG_PSPOLL);
    *total_flags = flags;
    mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter);
    mutex_unlock(&dev->mutex);
}
static void
mt7601u_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
             struct ieee80211_bss_conf *info, u32 changed)
{
    struct mt7601u_dev *dev = hw->priv;
    mutex_lock(&dev->mutex);
    if (changed & BSS_CHANGED_ASSOC)
        mt7601u_phy_con_cal_onoff(dev, info);
    if (changed & BSS_CHANGED_BSSID) {
        mt7601u_addr_wr(dev, MT_MAC_BSSID_DW0, info->bssid);
        /* Note: this is a hack because beacon_int is not changed
         *     on leave nor is any more appropriate event generated.
         *     rt2x00 doesn't seem to be bothered though.
         */
        if (is_zero_ether_addr(info->bssid))
            mt7601u_mac_config_tsf(dev, false, 0);
    }
    if (changed & BSS_CHANGED_BASIC_RATES) {
        mt7601u_wr(dev, MT_LEGACY_BASIC_RATE, info->basic_rates);
        mt7601u_wr(dev, MT_HT_FBK_CFG0, 0x65432100);
        mt7601u_wr(dev, MT_HT_FBK_CFG1, 0xedcba980);
        mt7601u_wr(dev, MT_LG_FBK_CFG0, 0xedcba988);
        mt7601u_wr(dev, MT_LG_FBK_CFG1, 0x00002100);
    }
    if (changed & BSS_CHANGED_BEACON_INT)
        mt7601u_mac_config_tsf(dev, true, info->beacon_int);
    if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
        mt7601u_mac_set_protection(dev, info->use_cts_prot,
                       info->ht_operation_mode);
    if (changed & BSS_CHANGED_ERP_PREAMBLE)
        mt7601u_mac_set_short_preamble(dev, info->use_short_preamble);
    if (changed & BSS_CHANGED_ERP_SLOT) {
        int slottime = info->use_short_slot ? 9 : 20;
        mt76_rmw_field(dev, MT_BKOFF_SLOT_CFG,
                   MT_BKOFF_SLOT_CFG_SLOTTIME, slottime);
    }
    if (changed & BSS_CHANGED_ASSOC)
        mt7601u_phy_recalibrate_after_assoc(dev);
    mutex_unlock(&dev->mutex);
}
static int
mt76_wcid_alloc(struct mt7601u_dev *dev)
{
    int i, idx = 0;
    for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) {
        idx = ffs(~dev->wcid_mask[i]);
        if (!idx)
            continue;
        idx--;
        dev->wcid_mask[i] |= BIT(idx);
        break;
    }
    idx = i * BITS_PER_LONG + idx;
    if (idx > 119)
        return -1;
    return idx;
}
static int
mt7601u_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        struct ieee80211_sta *sta)
{
    struct mt7601u_dev *dev = hw->priv;
    struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
    struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
    int ret = 0;
    int idx = 0;
    mutex_lock(&dev->mutex);
    idx = mt76_wcid_alloc(dev);
    if (idx < 0) {
        ret = -ENOSPC;
        goto out;
    }
    msta->wcid.idx = idx;
    msta->wcid.hw_key_idx = -1;
    mt7601u_mac_wcid_setup(dev, idx, mvif->idx, sta->addr);
    mt76_clear(dev, MT_WCID_DROP(idx), MT_WCID_DROP_MASK(idx));
    rcu_assign_pointer(dev->wcid[idx], &msta->wcid);
    mt7601u_mac_set_ampdu_factor(dev);
out:
    mutex_unlock(&dev->mutex);
    return ret;
}
static int
mt7601u_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
           struct ieee80211_sta *sta)
{
    struct mt7601u_dev *dev = hw->priv;
    struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
    int idx = msta->wcid.idx;
    mutex_lock(&dev->mutex);
    rcu_assign_pointer(dev->wcid[idx], NULL);
    mt76_set(dev, MT_WCID_DROP(idx), MT_WCID_DROP_MASK(idx));
    dev->wcid_mask[idx / BITS_PER_LONG] &= ~BIT(idx % BITS_PER_LONG);
    mt7601u_mac_wcid_setup(dev, idx, 0, NULL);
    mt7601u_mac_set_ampdu_factor(dev);
    mutex_unlock(&dev->mutex);
    return 0;
}
static void
mt7601u_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
           enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
{
}
static void
mt7601u_sw_scan(struct ieee80211_hw *hw,
        struct ieee80211_vif *vif,
        const u8 *mac_addr)
{
    struct mt7601u_dev *dev = hw->priv;
    mt7601u_agc_save(dev);
    set_bit(MT7601U_STATE_SCANNING, &dev->state);
}
static void
mt7601u_sw_scan_complete(struct ieee80211_hw *hw,
             struct ieee80211_vif *vif)
{
    struct mt7601u_dev *dev = hw->priv;
    mt7601u_agc_restore(dev);
    clear_bit(MT7601U_STATE_SCANNING, &dev->state);
}
static int
mt7601u_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        struct ieee80211_vif *vif, struct ieee80211_sta *sta,
        struct ieee80211_key_conf *key)
{
    struct mt7601u_dev *dev = hw->priv;
    struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
    struct mt76_sta *msta = sta ? (struct mt76_sta *) sta->drv_priv : NULL;
    struct mt76_wcid *wcid = msta ? &msta->wcid : &mvif->group_wcid;
    int idx = key->keyidx;
    int ret;
    if (cmd == SET_KEY) {
        key->hw_key_idx = wcid->idx;
        wcid->hw_key_idx = idx;
    } else {
        if (idx == wcid->hw_key_idx)
            wcid->hw_key_idx = -1;
        key = NULL;
    }
    if (!msta) {
        if (key || wcid->hw_key_idx == idx) {
            ret = mt76_mac_wcid_set_key(dev, wcid->idx, key);
            if (ret)
                return ret;
        }
        return mt76_mac_shared_key_setup(dev, mvif->idx, idx, key);
    }
    return mt76_mac_wcid_set_key(dev, msta->wcid.idx, key);
}
static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
{
    struct mt7601u_dev *dev = hw->priv;
    mt76_rmw_field(dev, MT_TX_RTS_CFG, MT_TX_RTS_CFG_THRESH, value);
    return 0;
}
static int
mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
          struct ieee80211_ampdu_params *params
#else
          enum ieee80211_ampdu_mlme_action action,
          struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
          , bool amsdu
#endif
#endif
          )
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
    enum ieee80211_ampdu_mlme_action action = params->action;
    struct ieee80211_sta *sta = params->sta;
    u16 *ssn = &params->ssn;
    u16 tid = params->tid;
#endif
    struct mt7601u_dev *dev = hw->priv;
    struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
    WARN_ON(msta->wcid.idx > GROUP_WCID(0));
    switch (action) {
    case IEEE80211_AMPDU_RX_START:
        mt76_set(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, BIT(16 + tid));
        break;
    case IEEE80211_AMPDU_RX_STOP:
        mt76_clear(dev, MT_WCID_ADDR(msta->wcid.idx) + 4,
               BIT(16 + tid));
        break;
    case IEEE80211_AMPDU_TX_OPERATIONAL:
        ieee80211_send_bar(vif, sta->addr, tid, msta->agg_ssn[tid]);
        break;
    case IEEE80211_AMPDU_TX_STOP_FLUSH:
    case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
        break;
    case IEEE80211_AMPDU_TX_START:
        msta->agg_ssn[tid] = *ssn << 4;
        ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
        break;
    case IEEE80211_AMPDU_TX_STOP_CONT:
        ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
        break;
    }
    return 0;
}
static void
mt76_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
             struct ieee80211_sta *sta)
{
    struct mt7601u_dev *dev = hw->priv;
    struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
    struct ieee80211_sta_rates *rates;
    struct ieee80211_tx_rate rate = {};
    rcu_read_lock();
    rates = rcu_dereference(sta->rates);
    if (!rates)
        goto out;
    rate.idx = rates->rate[0].idx;
    rate.flags = rates->rate[0].flags;
    mt76_mac_wcid_set_rate(dev, &msta->wcid, &rate);
out:
    rcu_read_unlock();
}
const struct ieee80211_ops mt7601u_ops = {
    .tx = mt7601u_tx,
    .start = mt7601u_start,
    .stop = mt7601u_stop,
    .add_interface = mt7601u_add_interface,
    .remove_interface = mt7601u_remove_interface,
    .config = mt7601u_config,
    .configure_filter = mt76_configure_filter,
    .bss_info_changed = mt7601u_bss_info_changed,
    .sta_add = mt7601u_sta_add,
    .sta_remove = mt7601u_sta_remove,
    .sta_notify = mt7601u_sta_notify,
    .set_key = mt7601u_set_key,
    .conf_tx = mt7601u_conf_tx,
    .sw_scan_start = mt7601u_sw_scan,
    .sw_scan_complete = mt7601u_sw_scan_complete,
/*    .flush = mt7601u_flush,*/
    .ampdu_action = mt76_ampdu_action,
    .sta_rate_tbl_update = mt76_sta_rate_tbl_update,
    .set_rts_threshold = mt7601u_set_rts_threshold,
};
linux-bsp/drivers/mt7601u-sta/mcu.c
New file
@@ -0,0 +1,536 @@
/*
 * (c) Copyright 2002-2010, Ralink Technology, Inc.
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#include <linux/kernel.h>
#include <linux/firmware.h>
#include <linux/delay.h>
#include <linux/usb.h>
#include <linux/skbuff.h>
#include "mt7601u.h"
#include "dma.h"
#include "mcu.h"
#include "usb.h"
#include "trace.h"
#define MCU_FW_URB_MAX_PAYLOAD        0x3800
#define MCU_FW_URB_SIZE            (MCU_FW_URB_MAX_PAYLOAD + 12)
#define MCU_RESP_URB_SIZE        1024
static inline int firmware_running(struct mt7601u_dev *dev)
{
    return mt7601u_rr(dev, MT_MCU_COM_REG0) == 1;
}
static inline void skb_put_le32(struct sk_buff *skb, u32 val)
{
    put_unaligned_le32(val, skb_put(skb, 4));
}
static inline void mt7601u_dma_skb_wrap_cmd(struct sk_buff *skb,
                        u8 seq, enum mcu_cmd cmd)
{
    WARN_ON(mt7601u_dma_skb_wrap(skb, CPU_TX_PORT, DMA_COMMAND,
                     MT76_SET(MT_TXD_CMD_INFO_SEQ, seq) |
                     MT76_SET(MT_TXD_CMD_INFO_TYPE, cmd)));
}
static inline void trace_mt_mcu_msg_send_cs(struct mt7601u_dev *dev,
                        struct sk_buff *skb, bool need_resp)
{
    u32 i, csum = 0;
    for (i = 0; i < skb->len / 4; i++)
        csum ^= get_unaligned_le32(skb->data + i * 4);
    trace_mt_mcu_msg_send(dev, skb, csum, need_resp);
}
static struct sk_buff *
mt7601u_mcu_msg_alloc(struct mt7601u_dev *dev, const void *data, int len)
{
    struct sk_buff *skb;
    WARN_ON(len % 4); /* if length is not divisible by 4 we need to pad */
    skb = alloc_skb(len + MT_DMA_HDR_LEN + 4, GFP_KERNEL);
    skb_reserve(skb, MT_DMA_HDR_LEN);
    memcpy(skb_put(skb, len), data, len);
    return skb;
}
static int mt7601u_mcu_wait_resp(struct mt7601u_dev *dev, u8 seq)
{
    struct urb *urb = dev->mcu.resp.urb;
    u32 rxfce;
    int urb_status, ret, i = 5;
    while (i--) {
        if (!wait_for_completion_timeout(&dev->mcu.resp_cmpl,
                         msecs_to_jiffies(300))) {
            dev_warn(dev->dev, "Warning: %s retrying\n", __func__);
            continue;
        }
        /* Make copies of important data before reusing the urb */
        rxfce = get_unaligned_le32(dev->mcu.resp.buf);
        urb_status = urb->status * mt7601u_urb_has_error(urb);
        ret = mt7601u_usb_submit_buf(dev, USB_DIR_IN, MT_EP_IN_CMD_RESP,
                         &dev->mcu.resp, GFP_KERNEL,
                         mt7601u_complete_urb,
                         &dev->mcu.resp_cmpl);
        if (ret)
            return ret;
        if (urb_status)
            dev_err(dev->dev, "Error: MCU resp urb failed:%d\n",
                urb_status);
        if (MT76_GET(MT_RXD_CMD_INFO_CMD_SEQ, rxfce) == seq &&
            MT76_GET(MT_RXD_CMD_INFO_EVT_TYPE, rxfce) == CMD_DONE)
            return 0;
        dev_err(dev->dev, "Error: MCU resp evt:%hhx seq:%hhx-%hhx!\n",
            MT76_GET(MT_RXD_CMD_INFO_EVT_TYPE, rxfce),
            seq, MT76_GET(MT_RXD_CMD_INFO_CMD_SEQ, rxfce));
    }
    dev_err(dev->dev, "Error: %s timed out\n", __func__);
    return -ETIMEDOUT;
}
static int
mt7601u_mcu_msg_send(struct mt7601u_dev *dev, struct sk_buff *skb,
             enum mcu_cmd cmd, bool wait_resp)
{
    struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
    unsigned cmd_pipe = usb_sndbulkpipe(usb_dev,
                        dev->out_eps[MT_EP_OUT_INBAND_CMD]);
    int sent, ret;
    u8 seq = 0;
    if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
        return 0;
    mutex_lock(&dev->mcu.mutex);
    if (wait_resp)
        while (!seq)
            seq = ++dev->mcu.msg_seq & 0xf;
    mt7601u_dma_skb_wrap_cmd(skb, seq, cmd);
    if (dev->mcu.resp_cmpl.done)
        dev_err(dev->dev, "Error: MCU response pre-completed!\n");
    trace_mt_mcu_msg_send_cs(dev, skb, wait_resp);
    trace_mt_submit_urb_sync(dev, cmd_pipe, skb->len);
    ret = usb_bulk_msg(usb_dev, cmd_pipe, skb->data, skb->len, &sent, 500);
    if (ret) {
        dev_err(dev->dev, "Error: send MCU cmd failed:%d\n", ret);
        goto out;
    }
    if (sent != skb->len)
        dev_err(dev->dev, "Error: %s sent != skb->len\n", __func__);
    if (wait_resp)
        ret = mt7601u_mcu_wait_resp(dev, seq);
out:
    mutex_unlock(&dev->mcu.mutex);
    consume_skb(skb);
    return ret;
}
static int mt7601u_mcu_function_select(struct mt7601u_dev *dev,
                       enum mcu_function func, u32 val)
{
    struct sk_buff *skb;
    struct {
        __le32 id;
        __le32 value;
    } __packed __aligned(4) msg = {
        .id = cpu_to_le32(func),
        .value = cpu_to_le32(val),
    };
    skb = mt7601u_mcu_msg_alloc(dev, &msg, sizeof(msg));
    return mt7601u_mcu_msg_send(dev, skb, CMD_FUN_SET_OP, func == 5);
}
int mt7601u_mcu_tssi_read_kick(struct mt7601u_dev *dev, int use_hvga)
{
    int ret;
    if (!test_bit(MT7601U_STATE_MCU_RUNNING, &dev->state))
        return 0;
    ret = mt7601u_mcu_function_select(dev, ATOMIC_TSSI_SETTING,
                      use_hvga);
    if (ret) {
        dev_warn(dev->dev, "Warning: MCU TSSI read kick failed\n");
        return ret;
    }
    dev->tssi_read_trig = true;
    return 0;
}
int
mt7601u_mcu_calibrate(struct mt7601u_dev *dev, enum mcu_calibrate cal, u32 val)
{
    struct sk_buff *skb;
    struct {
        __le32 id;
        __le32 value;
    } __packed __aligned(4) msg = {
        .id = cpu_to_le32(cal),
        .value = cpu_to_le32(val),
    };
    skb = mt7601u_mcu_msg_alloc(dev, &msg, sizeof(msg));
    return mt7601u_mcu_msg_send(dev, skb, CMD_CALIBRATION_OP, true);
}
int mt7601u_write_reg_pairs(struct mt7601u_dev *dev, u32 base,
                const struct mt76_reg_pair *data, int n)
{
    const int max_vals_per_cmd = INBAND_PACKET_MAX_LEN / 8;
    struct sk_buff *skb;
    int cnt, i, ret;
    if (!n)
        return 0;
    cnt = min(max_vals_per_cmd, n);
    skb = alloc_skb(cnt * 8 + MT_DMA_HDR_LEN + 4, GFP_KERNEL);
    if (!skb)
        return -ENOMEM;
    skb_reserve(skb, MT_DMA_HDR_LEN);
    for (i = 0; i < cnt; i++) {
        skb_put_le32(skb, base + data[i].reg);
        skb_put_le32(skb, data[i].value);
    }
    ret = mt7601u_mcu_msg_send(dev, skb, CMD_RANDOM_WRITE, cnt == n);
    if (ret)
        return ret;
    return mt7601u_write_reg_pairs(dev, base, data + cnt, n - cnt);
}
int mt7601u_burst_write_regs(struct mt7601u_dev *dev, u32 offset,
                 const u32 *data, int n)
{
    const int max_regs_per_cmd = INBAND_PACKET_MAX_LEN / 4 - 1;
    struct sk_buff *skb;
    int cnt, i, ret;
    if (!n)
        return 0;
    cnt = min(max_regs_per_cmd, n);
    skb = alloc_skb(cnt * 4 + MT_DMA_HDR_LEN + 4, GFP_KERNEL);
    if (!skb)
        return -ENOMEM;
    skb_reserve(skb, MT_DMA_HDR_LEN);
    skb_put_le32(skb, MT_MCU_MEMMAP_WLAN + offset);
    for (i = 0; i < cnt; i++)
        skb_put_le32(skb, data[i]);
    ret = mt7601u_mcu_msg_send(dev, skb, CMD_BURST_WRITE, cnt == n);
    if (ret)
        return ret;
    return mt7601u_burst_write_regs(dev, offset + cnt * 4,
                    data + cnt, n - cnt);
}
struct mt76_fw_header {
    __le32 ilm_len;
    __le32 dlm_len;
    __le16 build_ver;
    __le16 fw_ver;
    u8 pad[4];
    char build_time[16];
};
struct mt76_fw {
    struct mt76_fw_header hdr;
    u8 ivb[MT_MCU_IVB_SIZE];
    u8 ilm[];
};
static int __mt7601u_dma_fw(struct mt7601u_dev *dev,
                const struct mt7601u_dma_buf *dma_buf,
                const void *data, u32 len, u32 dst_addr)
{
    DECLARE_COMPLETION_ONSTACK(cmpl);
    struct mt7601u_dma_buf buf = *dma_buf; /* we need to fake length */
    __le32 reg;
    u32 val;
    int ret;
    reg = cpu_to_le32(MT76_SET(MT_TXD_INFO_TYPE, DMA_PACKET) |
              MT76_SET(MT_TXD_INFO_D_PORT, CPU_TX_PORT) |
              MT76_SET(MT_TXD_INFO_LEN, len));
    memcpy(buf.buf, &reg, sizeof(reg));
    memcpy(buf.buf + sizeof(reg), data, len);
    memset(buf.buf + sizeof(reg) + len, 0, 8);
    ret = mt7601u_vendor_single_wr(dev, MT_VEND_WRITE_FCE,
                       MT_FCE_DMA_ADDR, dst_addr);
    if (ret)
        return ret;
    len = roundup(len, 4);
    ret = mt7601u_vendor_single_wr(dev, MT_VEND_WRITE_FCE,
                       MT_FCE_DMA_LEN, len << 16);
    if (ret)
        return ret;
    buf.len = MT_DMA_HDR_LEN + len + 4;
    ret = mt7601u_usb_submit_buf(dev, USB_DIR_OUT, MT_EP_OUT_INBAND_CMD,
                     &buf, GFP_KERNEL,
                     mt7601u_complete_urb, &cmpl);
    if (ret)
        return ret;
    if (!wait_for_completion_timeout(&cmpl, msecs_to_jiffies(1000))) {
        dev_err(dev->dev, "Error: firmware upload timed out\n");
        usb_kill_urb(buf.urb);
        return -ETIMEDOUT;
    }
    if (mt7601u_urb_has_error(buf.urb)) {
        dev_err(dev->dev, "Error: firmware upload urb failed:%d\n",
            buf.urb->status);
        return buf.urb->status;
    }
    val = mt7601u_rr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX);
    val++;
    mt7601u_wr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX, val);
    return 0;
}
static int
mt7601u_dma_fw(struct mt7601u_dev *dev, struct mt7601u_dma_buf *dma_buf,
           const void *data, int len, u32 dst_addr)
{
    int n, ret;
    if (len == 0)
        return 0;
    n = min(MCU_FW_URB_MAX_PAYLOAD, len);
    ret = __mt7601u_dma_fw(dev, dma_buf, data, n, dst_addr);
    if (ret)
        return ret;
    if (!mt76_poll_msec(dev, MT_MCU_COM_REG1, BIT(31), BIT(31), 500))
        return -ETIMEDOUT;
    return mt7601u_dma_fw(dev, dma_buf, data + n, len - n, dst_addr + n);
}
static int
mt7601u_upload_firmware(struct mt7601u_dev *dev, const struct mt76_fw *fw)
{
    struct mt7601u_dma_buf dma_buf;
    void *ivb;
    u32 ilm_len, dlm_len;
    int i, ret;
    ivb = kmemdup(fw->ivb, sizeof(fw->ivb), GFP_KERNEL);
    if (!ivb)
        return -ENOMEM;
    if (mt7601u_usb_alloc_buf(dev, MCU_FW_URB_SIZE, &dma_buf)) {
        ret = -ENOMEM;
        goto error;
    }
    ilm_len = le32_to_cpu(fw->hdr.ilm_len) - sizeof(fw->ivb);
    dev_dbg(dev->dev, "loading FW - ILM %u + IVB %zu\n",
        ilm_len, sizeof(fw->ivb));
    ret = mt7601u_dma_fw(dev, &dma_buf, fw->ilm, ilm_len, sizeof(fw->ivb));
    if (ret)
        goto error;
    dlm_len = le32_to_cpu(fw->hdr.dlm_len);
    dev_dbg(dev->dev, "loading FW - DLM %u\n", dlm_len);
    ret = mt7601u_dma_fw(dev, &dma_buf, fw->ilm + ilm_len,
                 dlm_len, MT_MCU_DLM_OFFSET);
    if (ret)
        goto error;
    ret = mt7601u_vendor_request(dev, MT_VEND_DEV_MODE, USB_DIR_OUT,
                     0x12, 0, ivb, sizeof(fw->ivb));
    if (ret < 0)
        goto error;
    ret = 0;
    for (i = 100; i && !firmware_running(dev); i--)
        msleep(10);
    if (!i) {
        ret = -ETIMEDOUT;
        goto error;
    }
    dev_dbg(dev->dev, "Firmware running!\n");
error:
    kfree(ivb);
    mt7601u_usb_free_buf(dev, &dma_buf);
    return ret;
}
static int mt7601u_load_firmware(struct mt7601u_dev *dev)
{
    const struct firmware *fw;
    const struct mt76_fw_header *hdr;
    int len, ret;
    u32 val;
    mt7601u_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN |
                     MT_USB_DMA_CFG_TX_BULK_EN));
    if (firmware_running(dev))
        return 0;
    ret = request_firmware(&fw, MT7601U_FIRMWARE, dev->dev);
    if (ret)
        return ret;
    if (!fw || !fw->data || fw->size < sizeof(*hdr))
        goto err_inv_fw;
    hdr = (const struct mt76_fw_header *) fw->data;
    if (le32_to_cpu(hdr->ilm_len) <= MT_MCU_IVB_SIZE)
        goto err_inv_fw;
    len = sizeof(*hdr);
    len += le32_to_cpu(hdr->ilm_len);
    len += le32_to_cpu(hdr->dlm_len);
    if (fw->size != len)
        goto err_inv_fw;
    val = le16_to_cpu(hdr->fw_ver);
    dev_info(dev->dev,
         "Firmware Version: %d.%d.%02d Build: %x Build time: %.16s\n",
         (val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf,
         le16_to_cpu(hdr->build_ver), hdr->build_time);
    len = le32_to_cpu(hdr->ilm_len);
    mt7601u_wr(dev, 0x94c, 0);
    mt7601u_wr(dev, MT_FCE_PSE_CTRL, 0);
    mt7601u_vendor_reset(dev);
    msleep(5);
    mt7601u_wr(dev, 0xa44, 0);
    mt7601u_wr(dev, 0x230, 0x84210);
    mt7601u_wr(dev, 0x400, 0x80c00);
    mt7601u_wr(dev, 0x800, 1);
    mt7601u_rmw(dev, MT_PBF_CFG, 0, (MT_PBF_CFG_TX0Q_EN |
                     MT_PBF_CFG_TX1Q_EN |
                     MT_PBF_CFG_TX2Q_EN |
                     MT_PBF_CFG_TX3Q_EN));
    mt7601u_wr(dev, MT_FCE_PSE_CTRL, 1);
    mt7601u_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN |
                     MT_USB_DMA_CFG_TX_BULK_EN));
    val = mt76_set(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_CLR);
    val &= ~MT_USB_DMA_CFG_TX_CLR;
    mt7601u_wr(dev, MT_USB_DMA_CFG, val);
    /* FCE tx_fs_base_ptr */
    mt7601u_wr(dev, MT_TX_CPU_FROM_FCE_BASE_PTR, 0x400230);
    /* FCE tx_fs_max_cnt */
    mt7601u_wr(dev, MT_TX_CPU_FROM_FCE_MAX_COUNT, 1);
    /* FCE pdma enable */
    mt7601u_wr(dev, MT_FCE_PDMA_GLOBAL_CONF, 0x44);
    /* FCE skip_fs_en */
    mt7601u_wr(dev, MT_FCE_SKIP_FS, 3);
    ret = mt7601u_upload_firmware(dev, (const struct mt76_fw *)fw->data);
    release_firmware(fw);
    return ret;
err_inv_fw:
    dev_err(dev->dev, "Invalid firmware image\n");
    release_firmware(fw);
    return -ENOENT;
}
int mt7601u_mcu_init(struct mt7601u_dev *dev)
{
    int ret;
    mutex_init(&dev->mcu.mutex);
    ret = mt7601u_load_firmware(dev);
    if (ret)
        return ret;
    set_bit(MT7601U_STATE_MCU_RUNNING, &dev->state);
    return 0;
}
int mt7601u_mcu_cmd_init(struct mt7601u_dev *dev)
{
    int ret;
    ret = mt7601u_mcu_function_select(dev, Q_SELECT, 1);
    if (ret)
        return ret;
    init_completion(&dev->mcu.resp_cmpl);
    if (mt7601u_usb_alloc_buf(dev, MCU_RESP_URB_SIZE, &dev->mcu.resp)) {
        mt7601u_usb_free_buf(dev, &dev->mcu.resp);
        return -ENOMEM;
    }
    ret = mt7601u_usb_submit_buf(dev, USB_DIR_IN, MT_EP_IN_CMD_RESP,
                     &dev->mcu.resp, GFP_KERNEL,
                     mt7601u_complete_urb, &dev->mcu.resp_cmpl);
    if (ret) {
        mt7601u_usb_free_buf(dev, &dev->mcu.resp);
        return ret;
    }
    return 0;
}
void mt7601u_mcu_cmd_deinit(struct mt7601u_dev *dev)
{
    usb_kill_urb(dev->mcu.resp.urb);
    mt7601u_usb_free_buf(dev, &dev->mcu.resp);
}
linux-bsp/drivers/mt7601u-sta/mcu.h
New file
@@ -0,0 +1,94 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#ifndef __MT7601U_MCU_H
#define __MT7601U_MCU_H
struct mt7601u_dev;
/* Register definitions */
#define MT_MCU_RESET_CTL        0x070C
#define MT_MCU_INT_LEVEL        0x0718
#define MT_MCU_COM_REG0            0x0730
#define MT_MCU_COM_REG1            0x0734
#define MT_MCU_COM_REG2            0x0738
#define MT_MCU_COM_REG3            0x073C
#define MT_MCU_IVB_SIZE            0x40
#define MT_MCU_DLM_OFFSET        0x80000
#define MT_MCU_MEMMAP_WLAN        0x00410000
#define MT_MCU_MEMMAP_BBP        0x40000000
#define MT_MCU_MEMMAP_RF        0x80000000
#define INBAND_PACKET_MAX_LEN        192
enum mcu_cmd {
    CMD_FUN_SET_OP = 1,
    CMD_LOAD_CR = 2,
    CMD_INIT_GAIN_OP = 3,
    CMD_DYNC_VGA_OP = 6,
    CMD_TDLS_CH_SW = 7,
    CMD_BURST_WRITE = 8,
    CMD_READ_MODIFY_WRITE = 9,
    CMD_RANDOM_READ = 10,
    CMD_BURST_READ = 11,
    CMD_RANDOM_WRITE = 12,
    CMD_LED_MODE_OP = 16,
    CMD_POWER_SAVING_OP = 20,
    CMD_WOW_CONFIG = 21,
    CMD_WOW_QUERY = 22,
    CMD_WOW_FEATURE = 24,
    CMD_CARRIER_DETECT_OP = 28,
    CMD_RADOR_DETECT_OP = 29,
    CMD_SWITCH_CHANNEL_OP = 30,
    CMD_CALIBRATION_OP = 31,
    CMD_BEACON_OP = 32,
    CMD_ANTENNA_OP = 33,
};
enum mcu_function {
    Q_SELECT = 1,
    ATOMIC_TSSI_SETTING = 5,
};
enum mcu_power_mode {
    RADIO_OFF = 0x30,
    RADIO_ON = 0x31,
    RADIO_OFF_AUTO_WAKEUP = 0x32,
    RADIO_OFF_ADVANCE = 0x33,
    RADIO_ON_ADVANCE = 0x34,
};
enum mcu_calibrate {
    MCU_CAL_R = 1,
    MCU_CAL_DCOC,
    MCU_CAL_LC,
    MCU_CAL_LOFT,
    MCU_CAL_TXIQ,
    MCU_CAL_BW,
    MCU_CAL_DPD,
    MCU_CAL_RXIQ,
    MCU_CAL_TXDCOC,
};
int mt7601u_mcu_init(struct mt7601u_dev *dev);
int mt7601u_mcu_cmd_init(struct mt7601u_dev *dev);
void mt7601u_mcu_cmd_deinit(struct mt7601u_dev *dev);
int
mt7601u_mcu_calibrate(struct mt7601u_dev *dev, enum mcu_calibrate cal, u32 val);
int mt7601u_mcu_tssi_read_kick(struct mt7601u_dev *dev, int use_hvga);
#endif
linux-bsp/drivers/mt7601u-sta/mt7601u.h
New file
@@ -0,0 +1,396 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#ifndef MT7601U_H
#define MT7601U_H
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/usb.h>
#include <linux/completion.h>
#include <net/mac80211.h>
#include <linux/debugfs.h>
#include "regs.h"
#include "util.h"
#define MT_CALIBRATE_INTERVAL        (4 * HZ)
#define MT_FREQ_CAL_INIT_DELAY        (30 * HZ)
#define MT_FREQ_CAL_CHECK_INTERVAL    (10 * HZ)
#define MT_FREQ_CAL_ADJ_INTERVAL    (HZ / 2)
#define MT_BBP_REG_VERSION        0x00
#define MT_USB_AGGR_SIZE_LIMIT        28 /* * 1024B */
#define MT_USB_AGGR_TIMEOUT        0x80 /* * 33ns */
#define MT_RX_ORDER            3
#define MT_RX_URB_SIZE            (PAGE_SIZE << MT_RX_ORDER)
struct mt7601u_dma_buf {
    struct urb *urb;
    void *buf;
    dma_addr_t dma;
    size_t len;
};
struct mt7601u_mcu {
    struct mutex mutex;
    u8 msg_seq;
    struct mt7601u_dma_buf resp;
    struct completion resp_cmpl;
};
struct mt7601u_freq_cal {
    struct delayed_work work;
    u8 freq;
    bool enabled;
    bool adjusting;
};
struct mac_stats {
    u64 rx_stat[6];
    u64 tx_stat[6];
    u64 aggr_stat[2];
    u64 aggr_n[32];
    u64 zero_len_del[2];
};
#define N_RX_ENTRIES    16
struct mt7601u_rx_queue {
    struct mt7601u_dev *dev;
    struct mt7601u_dma_buf_rx {
        struct urb *urb;
        struct page *p;
    } e[N_RX_ENTRIES];
    unsigned int start;
    unsigned int end;
    unsigned int entries;
    unsigned int pending;
};
#define N_TX_ENTRIES    64
struct mt7601u_tx_queue {
    struct mt7601u_dev *dev;
    struct mt7601u_dma_buf_tx {
        struct urb *urb;
        struct sk_buff *skb;
    } e[N_TX_ENTRIES];
    unsigned int start;
    unsigned int end;
    unsigned int entries;
    unsigned int used;
    unsigned int fifo_seq;
};
/* WCID allocation:
 *     0: mcast wcid
 *     1: bssid wcid
 *  1...: STAs
 * ...7e: group wcids
 *    7f: reserved
 */
#define N_WCIDS        128
#define GROUP_WCID(idx)    (N_WCIDS - 2 - idx)
struct mt7601u_eeprom_params;
#define MT_EE_TEMPERATURE_SLOPE        39
#define MT_FREQ_OFFSET_INVALID        -128
enum mt_temp_mode {
    MT_TEMP_MODE_NORMAL,
    MT_TEMP_MODE_HIGH,
    MT_TEMP_MODE_LOW,
};
enum mt_bw {
    MT_BW_20,
    MT_BW_40,
};
enum {
    MT7601U_STATE_INITIALIZED,
    MT7601U_STATE_REMOVED,
    MT7601U_STATE_WLAN_RUNNING,
    MT7601U_STATE_MCU_RUNNING,
    MT7601U_STATE_SCANNING,
    MT7601U_STATE_READING_STATS,
    MT7601U_STATE_MORE_STATS,
};
/**
 * struct mt7601u_dev - adapter structure
 * @lock:        protects @wcid->tx_rate.
 * @mac_lock:        locks out mac80211's tx status and rx paths.
 * @tx_lock:        protects @tx_q and changes of MT7601U_STATE_*_STATS
 *            flags in @state.
 * @rx_lock:        protects @rx_q.
 * @con_mon_lock:    protects @ap_bssid, @bcn_*, @avg_rssi.
 * @mutex:        ensures exclusive access from mac80211 callbacks.
 * @vendor_req_mutex:    protects @vend_buf, ensures atomicity of split writes.
 * @reg_atomic_mutex:    ensures atomicity of indirect register accesses
 *            (accesses to RF and BBP).
 * @hw_atomic_mutex:    ensures exclusive access to HW during critical
 *            operations (power management, channel switch).
 */
struct mt7601u_dev {
    struct ieee80211_hw *hw;
    struct device *dev;
    unsigned long state;
    struct mutex mutex;
    unsigned long wcid_mask[N_WCIDS / BITS_PER_LONG];
    struct cfg80211_chan_def chandef;
    struct ieee80211_supported_band *sband_2g;
    struct mt7601u_mcu mcu;
    struct delayed_work cal_work;
    struct delayed_work mac_work;
    struct workqueue_struct *stat_wq;
    struct delayed_work stat_work;
    struct mt76_wcid *mon_wcid;
    struct mt76_wcid __rcu *wcid[N_WCIDS];
    spinlock_t lock;
    spinlock_t mac_lock;
    const u16 *beacon_offsets;
    u8 macaddr[ETH_ALEN];
    struct mt7601u_eeprom_params *ee;
    struct mutex vendor_req_mutex;
    void *vend_buf;
    struct mutex reg_atomic_mutex;
    struct mutex hw_atomic_mutex;
    u32 rxfilter;
    u32 debugfs_reg;
    u8 out_eps[8];
    u8 in_eps[8];
    u16 out_max_packet;
    u16 in_max_packet;
    /* TX */
    spinlock_t tx_lock;
    struct tasklet_struct tx_tasklet;
    struct mt7601u_tx_queue *tx_q;
    struct sk_buff_head tx_skb_done;
    atomic_t avg_ampdu_len;
    /* RX */
    spinlock_t rx_lock;
    struct tasklet_struct rx_tasklet;
    struct mt7601u_rx_queue rx_q;
    /* Connection monitoring things */
    spinlock_t con_mon_lock;
    u8 ap_bssid[ETH_ALEN];
    s8 bcn_freq_off;
    u8 bcn_phy_mode;
    int avg_rssi; /* starts at 0 and converges */
    u8 agc_save;
    struct mt7601u_freq_cal freq_cal;
    bool tssi_read_trig;
    s8 tssi_init;
    s8 tssi_init_hvga;
    s16 tssi_init_hvga_offset_db;
    int prev_pwr_diff;
    enum mt_temp_mode temp_mode;
    int curr_temp;
    int dpd_temp;
    s8 raw_temp;
    bool pll_lock_protect;
    u8 bw;
    bool chan_ext_below;
    /* PA mode */
    u32 rf_pa_mode[2];
    struct mac_stats stats;
};
struct mt7601u_tssi_params {
    char tssi0;
    int trgt_power;
};
struct mt76_wcid {
    u8 idx;
    u8 hw_key_idx;
    u16 tx_rate;
    bool tx_rate_set;
    u8 tx_rate_nss;
};
struct mt76_vif {
    u8 idx;
    struct mt76_wcid group_wcid;
};
struct mt76_sta {
    struct mt76_wcid wcid;
    u16 agg_ssn[IEEE80211_NUM_TIDS];
};
struct mt76_reg_pair {
    u32 reg;
    u32 value;
};
struct mt7601u_rxwi;
extern const struct ieee80211_ops mt7601u_ops;
void mt7601u_init_debugfs(struct mt7601u_dev *dev);
u32 mt7601u_rr(struct mt7601u_dev *dev, u32 offset);
void mt7601u_wr(struct mt7601u_dev *dev, u32 offset, u32 val);
u32 mt7601u_rmw(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val);
u32 mt7601u_rmc(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val);
void mt7601u_wr_copy(struct mt7601u_dev *dev, u32 offset,
             const void *data, int len);
int mt7601u_wait_asic_ready(struct mt7601u_dev *dev);
bool mt76_poll(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val,
           int timeout);
bool mt76_poll_msec(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val,
            int timeout);
/* Compatibility with mt76 */
#define mt76_rmw_field(_dev, _reg, _field, _val)    \
    mt76_rmw(_dev, _reg, _field, MT76_SET(_field, _val))
static inline u32 mt76_rr(struct mt7601u_dev *dev, u32 offset)
{
    return mt7601u_rr(dev, offset);
}
static inline void mt76_wr(struct mt7601u_dev *dev, u32 offset, u32 val)
{
    return mt7601u_wr(dev, offset, val);
}
static inline u32
mt76_rmw(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val)
{
    return mt7601u_rmw(dev, offset, mask, val);
}
static inline u32 mt76_set(struct mt7601u_dev *dev, u32 offset, u32 val)
{
    return mt76_rmw(dev, offset, 0, val);
}
static inline u32 mt76_clear(struct mt7601u_dev *dev, u32 offset, u32 val)
{
    return mt76_rmw(dev, offset, val, 0);
}
int mt7601u_write_reg_pairs(struct mt7601u_dev *dev, u32 base,
                const struct mt76_reg_pair *data, int len);
int mt7601u_burst_write_regs(struct mt7601u_dev *dev, u32 offset,
                 const u32 *data, int n);
void mt7601u_addr_wr(struct mt7601u_dev *dev, const u32 offset, const u8 *addr);
/* Init */
struct mt7601u_dev *mt7601u_alloc_device(struct device *dev);
int mt7601u_init_hardware(struct mt7601u_dev *dev);
int mt7601u_register_device(struct mt7601u_dev *dev);
void mt7601u_cleanup(struct mt7601u_dev *dev);
int mt7601u_mac_start(struct mt7601u_dev *dev);
void mt7601u_mac_stop(struct mt7601u_dev *dev);
/* PHY */
int mt7601u_phy_init(struct mt7601u_dev *dev);
int mt7601u_wait_bbp_ready(struct mt7601u_dev *dev);
void mt7601u_set_rx_path(struct mt7601u_dev *dev, u8 path);
void mt7601u_set_tx_dac(struct mt7601u_dev *dev, u8 path);
int mt7601u_bbp_set_bw(struct mt7601u_dev *dev, int bw);
void mt7601u_agc_save(struct mt7601u_dev *dev);
void mt7601u_agc_restore(struct mt7601u_dev *dev);
int mt7601u_phy_set_channel(struct mt7601u_dev *dev,
                struct cfg80211_chan_def *chandef);
void mt7601u_phy_recalibrate_after_assoc(struct mt7601u_dev *dev);
int mt7601u_phy_get_rssi(struct mt7601u_dev *dev,
             struct mt7601u_rxwi *rxwi, u16 rate);
void mt7601u_phy_con_cal_onoff(struct mt7601u_dev *dev,
                   struct ieee80211_bss_conf *info);
/* MAC */
void mt7601u_mac_work(struct work_struct *work);
void mt7601u_mac_set_protection(struct mt7601u_dev *dev, bool legacy_prot,
                int ht_mode);
void mt7601u_mac_set_short_preamble(struct mt7601u_dev *dev, bool short_preamb);
void mt7601u_mac_config_tsf(struct mt7601u_dev *dev, bool enable, int interval);
void
mt7601u_mac_wcid_setup(struct mt7601u_dev *dev, u8 idx, u8 vif_idx, u8 *mac);
void mt7601u_mac_set_ampdu_factor(struct mt7601u_dev *dev);
/* TX */
void mt7601u_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
        struct sk_buff *skb);
int mt7601u_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
            u16 queue, const struct ieee80211_tx_queue_params *params);
void mt7601u_tx_status(struct mt7601u_dev *dev, struct sk_buff *skb);
void mt7601u_tx_stat(struct work_struct *work);
/* util */
void mt76_remove_hdr_pad(struct sk_buff *skb);
int mt76_insert_hdr_pad(struct sk_buff *skb);
u32 mt7601u_bbp_set_ctrlch(struct mt7601u_dev *dev, bool below);
static inline u32 mt7601u_mac_set_ctrlch(struct mt7601u_dev *dev, bool below)
{
    return mt7601u_rmc(dev, MT_TX_BAND_CFG, 1, below);
}
int mt7601u_dma_init(struct mt7601u_dev *dev);
void mt7601u_dma_cleanup(struct mt7601u_dev *dev);
int mt7601u_dma_enqueue_tx(struct mt7601u_dev *dev, struct sk_buff *skb,
               struct mt76_wcid *wcid, int hw_q);
#endif
linux-bsp/drivers/mt7601u-sta/phy.c
New file
@@ -0,0 +1,1251 @@
/*
 * (c) Copyright 2002-2010, Ralink Technology, Inc.
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#include "mt7601u.h"
#include "mcu.h"
#include "eeprom.h"
#include "trace.h"
#include "initvals_phy.h"
#include <linux/etherdevice.h>
static void mt7601u_agc_reset(struct mt7601u_dev *dev);
static int
mt7601u_rf_wr(struct mt7601u_dev *dev, u8 bank, u8 offset, u8 value)
{
    int ret = 0;
    if (WARN_ON(!test_bit(MT7601U_STATE_WLAN_RUNNING, &dev->state)) ||
        WARN_ON(offset > 63))
        return -EINVAL;
    if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
        return 0;
    mutex_lock(&dev->reg_atomic_mutex);
    if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100)) {
        ret = -ETIMEDOUT;
        goto out;
    }
    mt7601u_wr(dev, MT_RF_CSR_CFG, MT76_SET(MT_RF_CSR_CFG_DATA, value) |
                       MT76_SET(MT_RF_CSR_CFG_REG_BANK, bank) |
                       MT76_SET(MT_RF_CSR_CFG_REG_ID, offset) |
                       MT_RF_CSR_CFG_WR |
                       MT_RF_CSR_CFG_KICK);
    trace_rf_write(dev, bank, offset, value);
out:
    mutex_unlock(&dev->reg_atomic_mutex);
    if (ret < 0)
        dev_err(dev->dev, "Error: RF write %02hhx:%02hhx failed:%d!!\n",
            bank, offset, ret);
    return ret;
}
static int
mt7601u_rf_rr(struct mt7601u_dev *dev, u8 bank, u8 offset)
{
    int ret = -ETIMEDOUT;
    u32 val;
    if (WARN_ON(!test_bit(MT7601U_STATE_WLAN_RUNNING, &dev->state)) ||
        WARN_ON(offset > 63))
        return -EINVAL;
    if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
        return 0xff;
    mutex_lock(&dev->reg_atomic_mutex);
    if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100))
        goto out;
    mt7601u_wr(dev, MT_RF_CSR_CFG, MT76_SET(MT_RF_CSR_CFG_REG_BANK, bank) |
                       MT76_SET(MT_RF_CSR_CFG_REG_ID, offset) |
                       MT_RF_CSR_CFG_KICK);
    if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100))
        goto out;
    val = mt7601u_rr(dev, MT_RF_CSR_CFG);
    if (MT76_GET(MT_RF_CSR_CFG_REG_ID, val) == offset &&
        MT76_GET(MT_RF_CSR_CFG_REG_BANK, val) == bank) {
        ret = MT76_GET(MT_RF_CSR_CFG_DATA, val);
        trace_rf_read(dev, bank, offset, ret);
    }
out:
    mutex_unlock(&dev->reg_atomic_mutex);
    if (ret < 0)
        dev_err(dev->dev, "Error: RF read %02hhx:%02hhx failed:%d!!\n",
            bank, offset, ret);
    return ret;
}
static int
mt7601u_rf_rmw(struct mt7601u_dev *dev, u8 bank, u8 offset, u8 mask, u8 val)
{
    int ret;
    ret = mt7601u_rf_rr(dev, bank, offset);
    if (ret < 0)
        return ret;
    val |= ret & ~mask;
    ret = mt7601u_rf_wr(dev, bank, offset, val);
    if (ret)
        return ret;
    return val;
}
static int
mt7601u_rf_set(struct mt7601u_dev *dev, u8 bank, u8 offset, u8 val)
{
    return mt7601u_rf_rmw(dev, bank, offset, 0, val);
}
static int
mt7601u_rf_clear(struct mt7601u_dev *dev, u8 bank, u8 offset, u8 mask)
{
    return mt7601u_rf_rmw(dev, bank, offset, mask, 0);
}
static void mt7601u_bbp_wr(struct mt7601u_dev *dev, u8 offset, u8 val)
{
    if (WARN_ON(!test_bit(MT7601U_STATE_WLAN_RUNNING, &dev->state)) ||
        test_bit(MT7601U_STATE_REMOVED, &dev->state))
        return;
    mutex_lock(&dev->reg_atomic_mutex);
    if (!mt76_poll(dev, MT_BBP_CSR_CFG, MT_BBP_CSR_CFG_BUSY, 0, 1000)) {
        dev_err(dev->dev, "Error: BBP write %02hhx failed!!\n", offset);
        goto out;
    }
    mt7601u_wr(dev, MT_BBP_CSR_CFG,
           MT76_SET(MT_BBP_CSR_CFG_VAL, val) |
           MT76_SET(MT_BBP_CSR_CFG_REG_NUM, offset) |
           MT_BBP_CSR_CFG_RW_MODE | MT_BBP_CSR_CFG_BUSY);
    trace_bbp_write(dev, offset, val);
out:
    mutex_unlock(&dev->reg_atomic_mutex);
}
static int mt7601u_bbp_rr(struct mt7601u_dev *dev, u8 offset)
{
    u32 val;
    int ret = -ETIMEDOUT;
    if (WARN_ON(!test_bit(MT7601U_STATE_WLAN_RUNNING, &dev->state)))
        return -EINVAL;
    if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
        return 0xff;
    mutex_lock(&dev->reg_atomic_mutex);
    if (!mt76_poll(dev, MT_BBP_CSR_CFG, MT_BBP_CSR_CFG_BUSY, 0, 1000))
        goto out;
    mt7601u_wr(dev, MT_BBP_CSR_CFG,
           MT76_SET(MT_BBP_CSR_CFG_REG_NUM, offset) |
           MT_BBP_CSR_CFG_RW_MODE | MT_BBP_CSR_CFG_BUSY |
           MT_BBP_CSR_CFG_READ);
    if (!mt76_poll(dev, MT_BBP_CSR_CFG, MT_BBP_CSR_CFG_BUSY, 0, 1000))
        goto out;
    val = mt7601u_rr(dev, MT_BBP_CSR_CFG);
    if (MT76_GET(MT_BBP_CSR_CFG_REG_NUM, val) == offset) {
        ret = MT76_GET(MT_BBP_CSR_CFG_VAL, val);
        trace_bbp_read(dev, offset, ret);
    }
out:
    mutex_unlock(&dev->reg_atomic_mutex);
    if (ret < 0)
        dev_err(dev->dev, "Error: BBP read %02hhx failed:%d!!\n",
            offset, ret);
    return ret;
}
static int mt7601u_bbp_rmw(struct mt7601u_dev *dev, u8 offset, u8 mask, u8 val)
{
    int ret;
    ret = mt7601u_bbp_rr(dev, offset);
    if (ret < 0)
        return ret;
    val |= ret & ~mask;
    mt7601u_bbp_wr(dev, offset, val);
    return val;
}
static u8 mt7601u_bbp_rmc(struct mt7601u_dev *dev, u8 offset, u8 mask, u8 val)
{
    int ret;
    ret = mt7601u_bbp_rr(dev, offset);
    if (ret < 0)
        return ret;
    val |= ret & ~mask;
    if (ret != val)
        mt7601u_bbp_wr(dev, offset, val);
    return val;
}
int mt7601u_wait_bbp_ready(struct mt7601u_dev *dev)
{
    int i = 20;
    u8 val;
    do {
        val = mt7601u_bbp_rr(dev, MT_BBP_REG_VERSION);
        if (val && ~val)
            break;
    } while (--i);
    if (!i) {
        dev_err(dev->dev, "Error: BBP is not ready\n");
        return -EIO;
    }
    return 0;
}
u32 mt7601u_bbp_set_ctrlch(struct mt7601u_dev *dev, bool below)
{
    return mt7601u_bbp_rmc(dev, 3, 0x20, below ? 0x20 : 0);
}
int mt7601u_phy_get_rssi(struct mt7601u_dev *dev,
             struct mt7601u_rxwi *rxwi, u16 rate)
{
    static const s8 lna[2][2][3] = {
        /* main LNA */ {
            /* bw20 */ { -2, 15, 33 },
            /* bw40 */ {  0, 16, 34 }
        },
        /*  aux LNA */ {
            /* bw20 */ { -2, 15, 33 },
            /* bw40 */ { -2, 16, 34 }
        }
    };
    int bw = MT76_GET(MT_RXWI_RATE_BW, rate);
    int aux_lna = MT76_GET(MT_RXWI_ANT_AUX_LNA, rxwi->ant);
    int lna_id = MT76_GET(MT_RXWI_GAIN_RSSI_LNA_ID, rxwi->gain);
    int val;
    if (lna_id) /* LNA id can be 0, 2, 3. */
        lna_id--;
    val = 8;
    val -= lna[aux_lna][bw][lna_id];
    val -= MT76_GET(MT_RXWI_GAIN_RSSI_VAL, rxwi->gain);
    val -= dev->ee->lna_gain;
    val -= dev->ee->rssi_offset[0];
    return val;
}
static void mt7601u_vco_cal(struct mt7601u_dev *dev)
{
    mt7601u_rf_wr(dev, 0, 4, 0x0a);
    mt7601u_rf_wr(dev, 0, 5, 0x20);
    mt7601u_rf_set(dev, 0, 4, BIT(7));
    msleep(2);
}
static int mt7601u_set_bw_filter(struct mt7601u_dev *dev, bool cal)
{
    u32 filter = 0;
    int ret;
    if (!cal)
        filter |= 0x10000;
    if (dev->bw != MT_BW_20)
        filter |= 0x00100;
    /* TX */
    ret = mt7601u_mcu_calibrate(dev, MCU_CAL_BW, filter | 1);
    if (ret)
        return ret;
    /* RX */
    return mt7601u_mcu_calibrate(dev, MCU_CAL_BW, filter);
}
static int mt7601u_load_bbp_temp_table_bw(struct mt7601u_dev *dev)
{
    const struct reg_table *t;
    if (WARN_ON(dev->temp_mode > MT_TEMP_MODE_LOW))
        return -EINVAL;
    t = &bbp_mode_table[dev->temp_mode][dev->bw];
    return mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP, t->regs, t->n);
}
static int mt7601u_bbp_temp(struct mt7601u_dev *dev, int mode, const char *name)
{
    const struct reg_table *t;
    int ret;
    if (dev->temp_mode == mode)
        return 0;
    dev->temp_mode = mode;
    trace_temp_mode(dev, mode);
    t = bbp_mode_table[dev->temp_mode];
    ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP,
                      t[2].regs, t[2].n);
    if (ret)
        return ret;
    return mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP,
                       t[dev->bw].regs, t[dev->bw].n);
}
static void mt7601u_apply_ch14_fixup(struct mt7601u_dev *dev, int hw_chan)
{
    struct mt7601u_rate_power *t = &dev->ee->power_rate_table;
    if (hw_chan != 14 || dev->bw != MT_BW_20) {
        mt7601u_bbp_rmw(dev, 4, 0x20, 0);
        mt7601u_bbp_wr(dev, 178, 0xff);
        t->cck[0].bw20 = dev->ee->real_cck_bw20[0];
        t->cck[1].bw20 = dev->ee->real_cck_bw20[1];
    } else { /* Apply CH14 OBW fixup */
        mt7601u_bbp_wr(dev, 4, 0x60);
        mt7601u_bbp_wr(dev, 178, 0);
        /* Note: vendor code is buggy here for negative values */
        t->cck[0].bw20 = dev->ee->real_cck_bw20[0] - 2;
        t->cck[1].bw20 = dev->ee->real_cck_bw20[1] - 2;
    }
}
static int __mt7601u_phy_set_channel(struct mt7601u_dev *dev,
                     struct cfg80211_chan_def *chandef)
{
#define FREQ_PLAN_REGS    4
    static const u8 freq_plan[14][FREQ_PLAN_REGS] = {
        { 0x99,    0x99,    0x09,    0x50 },
        { 0x46,    0x44,    0x0a,    0x50 },
        { 0xec,    0xee,    0x0a,    0x50 },
        { 0x99,    0x99,    0x0b,    0x50 },
        { 0x46,    0x44,    0x08,    0x51 },
        { 0xec,    0xee,    0x08,    0x51 },
        { 0x99,    0x99,    0x09,    0x51 },
        { 0x46,    0x44,    0x0a,    0x51 },
        { 0xec,    0xee,    0x0a,    0x51 },
        { 0x99,    0x99,    0x0b,    0x51 },
        { 0x46,    0x44,    0x08,    0x52 },
        { 0xec,    0xee,    0x08,    0x52 },
        { 0x99,    0x99,    0x09,    0x52 },
        { 0x33,    0x33,    0x0b,    0x52 },
    };
    struct mt76_reg_pair channel_freq_plan[FREQ_PLAN_REGS] = {
        { 17, 0 }, { 18, 0 }, { 19, 0 }, { 20, 0 },
    };
    struct mt76_reg_pair bbp_settings[3] = {
        { 62, 0x37 - dev->ee->lna_gain },
        { 63, 0x37 - dev->ee->lna_gain },
        { 64, 0x37 - dev->ee->lna_gain },
    };
    struct ieee80211_channel *chan = chandef->chan;
    enum nl80211_channel_type chan_type =
        cfg80211_get_chandef_type(chandef);
    struct mt7601u_rate_power *t = &dev->ee->power_rate_table;
    int chan_idx;
    bool chan_ext_below;
    u8 bw;
    int i, ret;
    bw = MT_BW_20;
    chan_ext_below = (chan_type == NL80211_CHAN_HT40MINUS);
    chan_idx = chan->hw_value - 1;
    if (chandef->width == NL80211_CHAN_WIDTH_40) {
        bw = MT_BW_40;
        if (chan_idx > 1 && chan_type == NL80211_CHAN_HT40MINUS)
            chan_idx -= 2;
        else if (chan_idx < 12 && chan_type == NL80211_CHAN_HT40PLUS)
            chan_idx += 2;
        else
            dev_err(dev->dev, "Error: invalid 40MHz channel!!\n");
    }
    if (bw != dev->bw || chan_ext_below != dev->chan_ext_below) {
        dev_dbg(dev->dev, "Info: switching HT mode bw:%d below:%d\n",
            bw, chan_ext_below);
        mt7601u_bbp_set_bw(dev, bw);
        mt7601u_bbp_set_ctrlch(dev, chan_ext_below);
        mt7601u_mac_set_ctrlch(dev, chan_ext_below);
        dev->chan_ext_below = chan_ext_below;
    }
    for (i = 0; i < FREQ_PLAN_REGS; i++)
        channel_freq_plan[i].value = freq_plan[chan_idx][i];
    ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_RF,
                      channel_freq_plan, FREQ_PLAN_REGS);
    if (ret)
        return ret;
    mt7601u_rmw(dev, MT_TX_ALC_CFG_0, 0x3f3f,
            dev->ee->chan_pwr[chan_idx] & 0x3f);
    ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP,
                      bbp_settings, ARRAY_SIZE(bbp_settings));
    if (ret)
        return ret;
    mt7601u_vco_cal(dev);
    mt7601u_bbp_set_bw(dev, bw);
    ret = mt7601u_set_bw_filter(dev, false);
    if (ret)
        return ret;
    mt7601u_apply_ch14_fixup(dev, chan->hw_value);
    mt7601u_wr(dev, MT_TX_PWR_CFG_0, int_to_s6(t->ofdm[1].bw20) << 24 |
                     int_to_s6(t->ofdm[0].bw20) << 16 |
                     int_to_s6(t->cck[1].bw20) << 8 |
                     int_to_s6(t->cck[0].bw20));
    if (test_bit(MT7601U_STATE_SCANNING, &dev->state))
        mt7601u_agc_reset(dev);
    dev->chandef = *chandef;
    return 0;
}
int mt7601u_phy_set_channel(struct mt7601u_dev *dev,
                struct cfg80211_chan_def *chandef)
{
    int ret;
    cancel_delayed_work_sync(&dev->cal_work);
    cancel_delayed_work_sync(&dev->freq_cal.work);
    mutex_lock(&dev->hw_atomic_mutex);
    ret = __mt7601u_phy_set_channel(dev, chandef);
    mutex_unlock(&dev->hw_atomic_mutex);
    if (ret)
        return ret;
    if (test_bit(MT7601U_STATE_SCANNING, &dev->state))
        return 0;
    ieee80211_queue_delayed_work(dev->hw, &dev->cal_work,
                     MT_CALIBRATE_INTERVAL);
    if (dev->freq_cal.enabled)
        ieee80211_queue_delayed_work(dev->hw, &dev->freq_cal.work,
                         MT_FREQ_CAL_INIT_DELAY);
    return 0;
}
#define BBP_R47_FLAG        GENMASK(2, 0)
#define BBP_R47_F_TSSI        0
#define BBP_R47_F_PKT_T        1
#define BBP_R47_F_TX_RATE    2
#define BBP_R47_F_TEMP        4
/**
 * mt7601u_bbp_r47_get - read value through BBP R47/R49 pair
 * @dev:    pointer to adapter structure
 * @reg:    value of BBP R47 before the operation
 * @flag:    one of the BBP_R47_F_* flags
 *
 * Convenience helper for reading values through BBP R47/R49 pair.
 * Takes old value of BBP R47 as @reg, because callers usually have it
 * cached already.
 *
 * Return: value of BBP R49.
 */
static u8 mt7601u_bbp_r47_get(struct mt7601u_dev *dev, u8 reg, u8 flag)
{
    flag |= reg & ~BBP_R47_FLAG;
    mt7601u_bbp_wr(dev, 47, flag);
    usleep_range(500, 700);
    return mt7601u_bbp_rr(dev, 49);
}
static s8 mt7601u_read_bootup_temp(struct mt7601u_dev *dev)
{
    u8 bbp_val, temp;
    u32 rf_bp, rf_set;
    int i;
    rf_set = mt7601u_rr(dev, MT_RF_SETTING_0);
    rf_bp = mt7601u_rr(dev, MT_RF_BYPASS_0);
    mt7601u_wr(dev, MT_RF_BYPASS_0, 0);
    mt7601u_wr(dev, MT_RF_SETTING_0, 0x00000010);
    mt7601u_wr(dev, MT_RF_BYPASS_0, 0x00000010);
    bbp_val = mt7601u_bbp_rmw(dev, 47, 0, 0x10);
    mt7601u_bbp_wr(dev, 22, 0x40);
    for (i = 100; i && (bbp_val & 0x10); i--)
        bbp_val = mt7601u_bbp_rr(dev, 47);
    temp = mt7601u_bbp_r47_get(dev, bbp_val, BBP_R47_F_TEMP);
    mt7601u_bbp_wr(dev, 22, 0);
    bbp_val = mt7601u_bbp_rr(dev, 21);
    bbp_val |= 0x02;
    mt7601u_bbp_wr(dev, 21, bbp_val);
    bbp_val &= ~0x02;
    mt7601u_bbp_wr(dev, 21, bbp_val);
    mt7601u_wr(dev, MT_RF_BYPASS_0, 0);
    mt7601u_wr(dev, MT_RF_SETTING_0, rf_set);
    mt7601u_wr(dev, MT_RF_BYPASS_0, rf_bp);
    trace_read_temp(dev, temp);
    return temp;
}
static s8 mt7601u_read_temp(struct mt7601u_dev *dev)
{
    int i;
    u8 val;
    s8 temp;
    val = mt7601u_bbp_rmw(dev, 47, 0x7f, 0x10);
    /* Note: this rarely succeeds, temp can change even if it fails. */
    for (i = 100; i && (val & 0x10); i--)
        val = mt7601u_bbp_rr(dev, 47);
    temp = mt7601u_bbp_r47_get(dev, val, BBP_R47_F_TEMP);
    trace_read_temp(dev, temp);
    return temp;
}
static void mt7601u_rxdc_cal(struct mt7601u_dev *dev)
{
    static const struct mt76_reg_pair intro[] = {
        { 158, 0x8d }, { 159, 0xfc },
        { 158, 0x8c }, { 159, 0x4c },
    }, outro[] = {
        { 158, 0x8d }, { 159, 0xe0 },
    };
    u32 mac_ctrl;
    int i, ret;
    mac_ctrl = mt7601u_rr(dev, MT_MAC_SYS_CTRL);
    mt7601u_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_RX);
    ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP,
                      intro, ARRAY_SIZE(intro));
    if (ret)
        dev_err(dev->dev, "%s intro failed:%d\n", __func__, ret);
    for (i = 20; i; i--) {
        usleep_range(300, 500);
        mt7601u_bbp_wr(dev, 158, 0x8c);
        if (mt7601u_bbp_rr(dev, 159) == 0x0c)
            break;
    }
    if (!i)
        dev_err(dev->dev, "%s timed out\n", __func__);
    mt7601u_wr(dev, MT_MAC_SYS_CTRL, 0);
    ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP,
                      outro, ARRAY_SIZE(outro));
    if (ret)
        dev_err(dev->dev, "%s outro failed:%d\n", __func__, ret);
    mt7601u_wr(dev, MT_MAC_SYS_CTRL, mac_ctrl);
}
void mt7601u_phy_recalibrate_after_assoc(struct mt7601u_dev *dev)
{
    mt7601u_mcu_calibrate(dev, MCU_CAL_DPD, dev->curr_temp);
    mt7601u_rxdc_cal(dev);
}
/* Note: function copied from vendor driver */
static s16 lin2dBd(u16 linear)
{
    short exp = 0;
    unsigned int mantisa;
    int app, dBd;
    if (WARN_ON(!linear))
        return -10000;
    mantisa = linear;
    exp = fls(mantisa) - 16;
    if (exp > 0)
        mantisa >>= exp;
    else
        mantisa <<= abs(exp);
    if (mantisa <= 0xb800)
        app = (mantisa + (mantisa >> 3) + (mantisa >> 4) - 0x9600);
    else
        app = (mantisa - (mantisa >> 3) - (mantisa >> 6) - 0x5a00);
    if (app < 0)
        app = 0;
    dBd = ((15 + exp) << 15) + app;
    dBd = (dBd << 2) + (dBd << 1) + (dBd >> 6) + (dBd >> 7);
    dBd = (dBd >> 10);
    return dBd;
}
static void
mt7601u_set_initial_tssi(struct mt7601u_dev *dev, s16 tssi_db, s16 tssi_hvga_db)
{
    struct tssi_data *d = &dev->ee->tssi_data;
    int init_offset;
    init_offset = -((tssi_db * d->slope + d->offset[1]) / 4096) + 10;
    mt76_rmw(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP,
         int_to_s6(init_offset) & MT_TX_ALC_CFG_1_TEMP_COMP);
}
static void mt7601u_tssi_dc_gain_cal(struct mt7601u_dev *dev)
{
    u8 rf_vga, rf_mixer, bbp_r47;
    int i, j;
    s8 res[4];
    s16 tssi_init_db, tssi_init_hvga_db;
    mt7601u_wr(dev, MT_RF_SETTING_0, 0x00000030);
    mt7601u_wr(dev, MT_RF_BYPASS_0, 0x000c0030);
    mt7601u_wr(dev, MT_MAC_SYS_CTRL, 0);
    mt7601u_bbp_wr(dev, 58, 0);
    mt7601u_bbp_wr(dev, 241, 0x2);
    mt7601u_bbp_wr(dev, 23, 0x8);
    bbp_r47 = mt7601u_bbp_rr(dev, 47);
    /* Set VGA gain */
    rf_vga = mt7601u_rf_rr(dev, 5, 3);
    mt7601u_rf_wr(dev, 5, 3, 8);
    /* Mixer disable */
    rf_mixer = mt7601u_rf_rr(dev, 4, 39);
    mt7601u_rf_wr(dev, 4, 39, 0);
    for (i = 0; i < 4; i++) {
        mt7601u_rf_wr(dev, 4, 39, (i & 1) ? rf_mixer : 0);
        mt7601u_bbp_wr(dev, 23, (i < 2) ? 0x08 : 0x02);
        mt7601u_rf_wr(dev, 5, 3, (i < 2) ? 0x08 : 0x11);
        /* BBP TSSI initial and soft reset */
        mt7601u_bbp_wr(dev, 22, 0);
        mt7601u_bbp_wr(dev, 244, 0);
        mt7601u_bbp_wr(dev, 21, 1);
        udelay(1);
        mt7601u_bbp_wr(dev, 21, 0);
        /* TSSI measurement */
        mt7601u_bbp_wr(dev, 47, 0x50);
        mt7601u_bbp_wr(dev, (i & 1) ? 244 : 22, (i & 1) ? 0x31 : 0x40);
        for (j = 20; j; j--)
            if (!(mt7601u_bbp_rr(dev, 47) & 0x10))
                break;
        if (!j)
            dev_err(dev->dev, "%s timed out\n", __func__);
        /* TSSI read */
        mt7601u_bbp_wr(dev, 47, 0x40);
        res[i] = mt7601u_bbp_rr(dev, 49);
    }
    tssi_init_db = lin2dBd((short)res[1] - res[0]);
    tssi_init_hvga_db = lin2dBd(((short)res[3] - res[2]) * 4);
    dev->tssi_init = res[0];
    dev->tssi_init_hvga = res[2];
    dev->tssi_init_hvga_offset_db = tssi_init_hvga_db - tssi_init_db;
    dev_dbg(dev->dev,
        "TSSI_init:%hhx db:%hx hvga:%hhx hvga_db:%hx off_db:%hx\n",
        dev->tssi_init, tssi_init_db, dev->tssi_init_hvga,
        tssi_init_hvga_db, dev->tssi_init_hvga_offset_db);
    mt7601u_bbp_wr(dev, 22, 0);
    mt7601u_bbp_wr(dev, 244, 0);
    mt7601u_bbp_wr(dev, 21, 1);
    udelay(1);
    mt7601u_bbp_wr(dev, 21, 0);
    mt7601u_wr(dev, MT_RF_BYPASS_0, 0);
    mt7601u_wr(dev, MT_RF_SETTING_0, 0);
    mt7601u_rf_wr(dev, 5, 3, rf_vga);
    mt7601u_rf_wr(dev, 4, 39, rf_mixer);
    mt7601u_bbp_wr(dev, 47, bbp_r47);
    mt7601u_set_initial_tssi(dev, tssi_init_db, tssi_init_hvga_db);
}
static int mt7601u_temp_comp(struct mt7601u_dev *dev, bool on)
{
    int ret, temp, hi_temp = 400, lo_temp = -200;
    temp = (dev->raw_temp - dev->ee->ref_temp) * MT_EE_TEMPERATURE_SLOPE;
    dev->curr_temp = temp;
    /* DPD Calibration */
    if (temp - dev->dpd_temp > 450 || temp - dev->dpd_temp < -450) {
        dev->dpd_temp = temp;
        ret = mt7601u_mcu_calibrate(dev, MCU_CAL_DPD, dev->dpd_temp);
        if (ret)
            return ret;
        mt7601u_vco_cal(dev);
        dev_dbg(dev->dev, "Recalibrate DPD\n");
    }
    /* PLL Lock Protect */
    if (temp < -50 && !dev->pll_lock_protect) { /* < 20C */
        dev->pll_lock_protect =  true;
        mt7601u_rf_wr(dev, 4, 4, 6);
        mt7601u_rf_clear(dev, 4, 10, 0x30);
        dev_dbg(dev->dev, "PLL lock protect on - too cold\n");
    } else if (temp > 50 && dev->pll_lock_protect) { /* > 30C */
        dev->pll_lock_protect = false;
        mt7601u_rf_wr(dev, 4, 4, 0);
        mt7601u_rf_rmw(dev, 4, 10, 0x30, 0x10);
        dev_dbg(dev->dev, "PLL lock protect off\n");
    }
    if (on) {
        hi_temp -= 50;
        lo_temp -= 50;
    }
    /* BBP CR for H, L, N temperature */
    if (temp > hi_temp)
        return mt7601u_bbp_temp(dev, MT_TEMP_MODE_HIGH, "high");
    else if (temp > lo_temp)
        return mt7601u_bbp_temp(dev, MT_TEMP_MODE_NORMAL, "normal");
    else
        return mt7601u_bbp_temp(dev, MT_TEMP_MODE_LOW, "low");
}
/* Note: this is used only with TSSI, we can just use trgt_pwr from eeprom. */
static int mt7601u_current_tx_power(struct mt7601u_dev *dev)
{
    return dev->ee->chan_pwr[dev->chandef.chan->hw_value - 1];
}
static bool mt7601u_use_hvga(struct mt7601u_dev *dev)
{
    return !(mt7601u_current_tx_power(dev) > 20);
}
static s16
mt7601u_phy_rf_pa_mode_val(struct mt7601u_dev *dev, int phy_mode, int tx_rate)
{
    static const s16 decode_tb[] = { 0, 8847, -5734, -5734 };
    u32 reg;
    switch (phy_mode) {
    case MT_PHY_TYPE_OFDM:
        tx_rate += 4;
    case MT_PHY_TYPE_CCK:
        reg = dev->rf_pa_mode[0];
        break;
    default:
        reg = dev->rf_pa_mode[1];
        break;
    }
    return decode_tb[(reg >> (tx_rate * 2)) & 0x3];
}
static struct mt7601u_tssi_params
mt7601u_tssi_params_get(struct mt7601u_dev *dev)
{
    static const u8 ofdm_pkt2rate[8] = { 6, 4, 2, 0, 7, 5, 3, 1 };
    static const int static_power[4] = { 0, -49152, -98304, 49152 };
    struct mt7601u_tssi_params p;
    u8 bbp_r47, pkt_type, tx_rate;
    struct power_per_rate *rate_table;
    bbp_r47 = mt7601u_bbp_rr(dev, 47);
    p.tssi0 = mt7601u_bbp_r47_get(dev, bbp_r47, BBP_R47_F_TSSI);
    dev->raw_temp = mt7601u_bbp_r47_get(dev, bbp_r47, BBP_R47_F_TEMP);
    pkt_type = mt7601u_bbp_r47_get(dev, bbp_r47, BBP_R47_F_PKT_T);
    p.trgt_power = mt7601u_current_tx_power(dev);
    switch (pkt_type & 0x03) {
    case MT_PHY_TYPE_CCK:
        tx_rate = (pkt_type >> 4) & 0x03;
        rate_table = dev->ee->power_rate_table.cck;
        break;
    case MT_PHY_TYPE_OFDM:
        tx_rate = ofdm_pkt2rate[(pkt_type >> 4) & 0x07];
        rate_table = dev->ee->power_rate_table.ofdm;
        break;
    default:
        tx_rate = mt7601u_bbp_r47_get(dev, bbp_r47, BBP_R47_F_TX_RATE);
        tx_rate &= 0x7f;
        rate_table = dev->ee->power_rate_table.ht;
        break;
    }
    if (dev->bw == MT_BW_20)
        p.trgt_power += rate_table[tx_rate / 2].bw20;
    else
        p.trgt_power += rate_table[tx_rate / 2].bw40;
    p.trgt_power <<= 12;
    dev_dbg(dev->dev, "tx_rate:%02hhx pwr:%08x\n", tx_rate, p.trgt_power);
    p.trgt_power += mt7601u_phy_rf_pa_mode_val(dev, pkt_type & 0x03,
                           tx_rate);
    /* Channel 14, cck, bw20 */
    if ((pkt_type & 0x03) == MT_PHY_TYPE_CCK) {
        if (mt7601u_bbp_rr(dev, 4) & 0x20)
            p.trgt_power += mt7601u_bbp_rr(dev, 178) ? 18022 : 9830;
        else
            p.trgt_power += mt7601u_bbp_rr(dev, 178) ? 819 : 24576;
    }
    p.trgt_power += static_power[mt7601u_bbp_rr(dev, 1) & 0x03];
    p.trgt_power += dev->ee->tssi_data.tx0_delta_offset;
    dev_dbg(dev->dev,
        "tssi:%02hhx t_power:%08x temp:%02hhx pkt_type:%02hhx\n",
        p.tssi0, p.trgt_power, dev->raw_temp, pkt_type);
    return p;
}
static bool mt7601u_tssi_read_ready(struct mt7601u_dev *dev)
{
    return !(mt7601u_bbp_rr(dev, 47) & 0x10);
}
static int mt7601u_tssi_cal(struct mt7601u_dev *dev)
{
    struct mt7601u_tssi_params params;
    int curr_pwr, diff_pwr;
    char tssi_offset;
    s8 tssi_init;
    s16 tssi_m_dc, tssi_db;
    bool hvga;
    u32 val;
    if (!dev->ee->tssi_enabled)
        return 0;
    hvga = mt7601u_use_hvga(dev);
    if (!dev->tssi_read_trig)
        return mt7601u_mcu_tssi_read_kick(dev, hvga);
    if (!mt7601u_tssi_read_ready(dev))
        return 0;
    params = mt7601u_tssi_params_get(dev);
    tssi_init = (hvga ? dev->tssi_init_hvga : dev->tssi_init);
    tssi_m_dc = params.tssi0 - tssi_init;
    tssi_db = lin2dBd(tssi_m_dc);
    dev_dbg(dev->dev, "tssi dc:%04hx db:%04hx hvga:%d\n",
        tssi_m_dc, tssi_db, hvga);
    if (dev->chandef.chan->hw_value < 5)
        tssi_offset = dev->ee->tssi_data.offset[0];
    else if (dev->chandef.chan->hw_value < 9)
        tssi_offset = dev->ee->tssi_data.offset[1];
    else
        tssi_offset = dev->ee->tssi_data.offset[2];
    if (hvga)
        tssi_db -= dev->tssi_init_hvga_offset_db;
    curr_pwr = tssi_db * dev->ee->tssi_data.slope + (tssi_offset << 9);
    diff_pwr = params.trgt_power - curr_pwr;
    dev_dbg(dev->dev, "Power curr:%08x diff:%08x\n", curr_pwr, diff_pwr);
    if (params.tssi0 > 126 && diff_pwr > 0) {
        dev_err(dev->dev, "Error: TSSI upper saturation\n");
        diff_pwr = 0;
    }
    if (params.tssi0 - tssi_init < 1 && diff_pwr < 0) {
        dev_err(dev->dev, "Error: TSSI lower saturation\n");
        diff_pwr = 0;
    }
    if ((dev->prev_pwr_diff ^ diff_pwr) < 0 && abs(diff_pwr) < 4096 &&
        (abs(diff_pwr) > abs(dev->prev_pwr_diff) ||
         (diff_pwr > 0 && diff_pwr == -dev->prev_pwr_diff)))
        diff_pwr = 0;
    else
        dev->prev_pwr_diff = diff_pwr;
    diff_pwr += (diff_pwr > 0) ? 2048 : -2048;
    diff_pwr /= 4096;
    dev_dbg(dev->dev, "final diff: %08x\n", diff_pwr);
    val = mt7601u_rr(dev, MT_TX_ALC_CFG_1);
    curr_pwr = s6_to_int(MT76_GET(MT_TX_ALC_CFG_1_TEMP_COMP, val));
    diff_pwr += curr_pwr;
    val = (val & ~MT_TX_ALC_CFG_1_TEMP_COMP) | int_to_s6(diff_pwr);
    mt7601u_wr(dev, MT_TX_ALC_CFG_1, val);
    return mt7601u_mcu_tssi_read_kick(dev, hvga);
}
static u8 mt7601u_agc_default(struct mt7601u_dev *dev)
{
    return (dev->ee->lna_gain - 8) * 2 + 0x34;
}
static void mt7601u_agc_reset(struct mt7601u_dev *dev)
{
    u8 agc = mt7601u_agc_default(dev);
    mt7601u_bbp_wr(dev, 66,    agc);
}
void mt7601u_agc_save(struct mt7601u_dev *dev)
{
    dev->agc_save = mt7601u_bbp_rr(dev, 66);
}
void mt7601u_agc_restore(struct mt7601u_dev *dev)
{
    mt7601u_bbp_wr(dev, 66, dev->agc_save);
}
static void mt7601u_agc_tune(struct mt7601u_dev *dev)
{
    u8 val = mt7601u_agc_default(dev);
    if (test_bit(MT7601U_STATE_SCANNING, &dev->state))
        return;
    /* Note: only in STA mode and not dozing; perhaps do this only if
     *     there is enough rssi updates since last run?
     *     Rssi updates are only on beacons and U2M so should work...
     */
    spin_lock_bh(&dev->con_mon_lock);
    if (dev->avg_rssi <= -70)
        val -= 0x20;
    else if (dev->avg_rssi <= -60)
        val -= 0x10;
    spin_unlock_bh(&dev->con_mon_lock);
    if (val != mt7601u_bbp_rr(dev, 66))
        mt7601u_bbp_wr(dev, 66, val);
    /* TODO: also if lost a lot of beacons try resetting
     *       (see RTMPSetAGCInitValue() call in mlme.c).
     */
}
static void mt7601u_phy_calibrate(struct work_struct *work)
{
    struct mt7601u_dev *dev = container_of(work, struct mt7601u_dev,
                        cal_work.work);
    mt7601u_agc_tune(dev);
    mt7601u_tssi_cal(dev);
    /* If TSSI calibration was run it already updated temperature. */
    if (!dev->ee->tssi_enabled)
        dev->raw_temp = mt7601u_read_temp(dev);
    mt7601u_temp_comp(dev, true); /* TODO: find right value for @on */
    ieee80211_queue_delayed_work(dev->hw, &dev->cal_work,
                     MT_CALIBRATE_INTERVAL);
}
static unsigned long
__mt7601u_phy_freq_cal(struct mt7601u_dev *dev, s8 last_offset, u8 phy_mode)
{
    u8 activate_threshold, deactivate_threshold;
    trace_freq_cal_offset(dev, phy_mode, last_offset);
    /* No beacons received - reschedule soon */
    if (last_offset == MT_FREQ_OFFSET_INVALID)
        return MT_FREQ_CAL_ADJ_INTERVAL;
    switch (phy_mode) {
    case MT_PHY_TYPE_CCK:
        activate_threshold = 19;
        deactivate_threshold = 5;
        break;
    case MT_PHY_TYPE_OFDM:
        activate_threshold = 102;
        deactivate_threshold = 32;
        break;
    case MT_PHY_TYPE_HT:
    case MT_PHY_TYPE_HT_GF:
        activate_threshold = 82;
        deactivate_threshold = 20;
        break;
    default:
        WARN_ON(1);
        return MT_FREQ_CAL_CHECK_INTERVAL;
    }
    if (abs(last_offset) >= activate_threshold)
        dev->freq_cal.adjusting = true;
    else if (abs(last_offset) <= deactivate_threshold)
        dev->freq_cal.adjusting = false;
    if (!dev->freq_cal.adjusting)
        return MT_FREQ_CAL_CHECK_INTERVAL;
    if (last_offset > deactivate_threshold) {
        if (dev->freq_cal.freq > 0)
            dev->freq_cal.freq--;
        else
            dev->freq_cal.adjusting = false;
    } else if (last_offset < -deactivate_threshold) {
        if (dev->freq_cal.freq < 0xbf)
            dev->freq_cal.freq++;
        else
            dev->freq_cal.adjusting = false;
    }
    trace_freq_cal_adjust(dev, dev->freq_cal.freq);
    mt7601u_rf_wr(dev, 0, 12, dev->freq_cal.freq);
    mt7601u_vco_cal(dev);
    return dev->freq_cal.adjusting ? MT_FREQ_CAL_ADJ_INTERVAL :
                     MT_FREQ_CAL_CHECK_INTERVAL;
}
static void mt7601u_phy_freq_cal(struct work_struct *work)
{
    struct mt7601u_dev *dev = container_of(work, struct mt7601u_dev,
                           freq_cal.work.work);
    s8 last_offset;
    u8 phy_mode;
    unsigned long delay;
    spin_lock_bh(&dev->con_mon_lock);
    last_offset = dev->bcn_freq_off;
    phy_mode = dev->bcn_phy_mode;
    spin_unlock_bh(&dev->con_mon_lock);
    delay = __mt7601u_phy_freq_cal(dev, last_offset, phy_mode);
    ieee80211_queue_delayed_work(dev->hw, &dev->freq_cal.work, delay);
    spin_lock_bh(&dev->con_mon_lock);
    dev->bcn_freq_off = MT_FREQ_OFFSET_INVALID;
    spin_unlock_bh(&dev->con_mon_lock);
}
void mt7601u_phy_con_cal_onoff(struct mt7601u_dev *dev,
                   struct ieee80211_bss_conf *info)
{
    if (!info->assoc)
        cancel_delayed_work_sync(&dev->freq_cal.work);
    /* Start/stop collecting beacon data */
    spin_lock_bh(&dev->con_mon_lock);
    ether_addr_copy(dev->ap_bssid, info->bssid);
    dev->avg_rssi = 0;
    dev->bcn_freq_off = MT_FREQ_OFFSET_INVALID;
    spin_unlock_bh(&dev->con_mon_lock);
    dev->freq_cal.freq = dev->ee->rf_freq_off;
    dev->freq_cal.enabled = info->assoc;
    dev->freq_cal.adjusting = false;
    if (info->assoc)
        ieee80211_queue_delayed_work(dev->hw, &dev->freq_cal.work,
                         MT_FREQ_CAL_INIT_DELAY);
}
static int mt7601u_init_cal(struct mt7601u_dev *dev)
{
    u32 mac_ctrl;
    int ret;
    dev->raw_temp = mt7601u_read_bootup_temp(dev);
    dev->curr_temp = (dev->raw_temp - dev->ee->ref_temp) *
        MT_EE_TEMPERATURE_SLOPE;
    dev->dpd_temp = dev->curr_temp;
    mac_ctrl = mt7601u_rr(dev, MT_MAC_SYS_CTRL);
    ret = mt7601u_mcu_calibrate(dev, MCU_CAL_R, 0);
    if (ret)
        return ret;
    ret = mt7601u_rf_rr(dev, 0, 4);
    if (ret < 0)
        return ret;
    ret |= 0x80;
    ret = mt7601u_rf_wr(dev, 0, 4, ret);
    if (ret)
        return ret;
    msleep(2);
    ret = mt7601u_mcu_calibrate(dev, MCU_CAL_TXDCOC, 0);
    if (ret)
        return ret;
    mt7601u_rxdc_cal(dev);
    ret = mt7601u_set_bw_filter(dev, true);
    if (ret)
        return ret;
    ret = mt7601u_mcu_calibrate(dev, MCU_CAL_LOFT, 0);
    if (ret)
        return ret;
    ret = mt7601u_mcu_calibrate(dev, MCU_CAL_TXIQ, 0);
    if (ret)
        return ret;
    ret = mt7601u_mcu_calibrate(dev, MCU_CAL_RXIQ, 0);
    if (ret)
        return ret;
    ret = mt7601u_mcu_calibrate(dev, MCU_CAL_DPD, dev->dpd_temp);
    if (ret)
        return ret;
    mt7601u_rxdc_cal(dev);
    mt7601u_tssi_dc_gain_cal(dev);
    mt7601u_wr(dev, MT_MAC_SYS_CTRL, mac_ctrl);
    mt7601u_temp_comp(dev, true);
    return 0;
}
int mt7601u_bbp_set_bw(struct mt7601u_dev *dev, int bw)
{
    u32 val, old;
    if (bw == dev->bw) {
        /* Vendor driver does the rmc even when no change is needed. */
        mt7601u_bbp_rmc(dev, 4, 0x18, bw == MT_BW_20 ? 0 : 0x10);
        return 0;
    }
    dev->bw = bw;
    /* Stop MAC for the time of bw change */
    old = mt7601u_rr(dev, MT_MAC_SYS_CTRL);
    val = old & ~(MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
    mt7601u_wr(dev, MT_MAC_SYS_CTRL, val);
    mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_TX | MT_MAC_STATUS_RX,
          0, 500000);
    mt7601u_bbp_rmc(dev, 4, 0x18, bw == MT_BW_20 ? 0 : 0x10);
    mt7601u_wr(dev, MT_MAC_SYS_CTRL, old);
    return mt7601u_load_bbp_temp_table_bw(dev);
}
/**
 * mt7601u_set_rx_path - set rx path in BBP
 * @dev:    pointer to adapter structure
 * @path:    rx path to set values are 0-based
 */
void mt7601u_set_rx_path(struct mt7601u_dev *dev, u8 path)
{
    mt7601u_bbp_rmw(dev, 3, 0x18, path << 3);
}
/**
 * mt7601u_set_tx_dac - set which tx DAC to use
 * @dev:    pointer to adapter structure
 * @path:    DAC index, values are 0-based
 */
void mt7601u_set_tx_dac(struct mt7601u_dev *dev, u8 dac)
{
    mt7601u_bbp_rmc(dev, 1, 0x18, dac << 3);
}
int mt7601u_phy_init(struct mt7601u_dev *dev)
{
    int ret;
    dev->rf_pa_mode[0] = mt7601u_rr(dev, MT_RF_PA_MODE_CFG0);
    dev->rf_pa_mode[1] = mt7601u_rr(dev, MT_RF_PA_MODE_CFG1);
    ret = mt7601u_rf_wr(dev, 0, 12, dev->ee->rf_freq_off);
    if (ret)
        return ret;
    ret = mt7601u_write_reg_pairs(dev, 0, rf_central,
                      ARRAY_SIZE(rf_central));
    if (ret)
        return ret;
    ret = mt7601u_write_reg_pairs(dev, 0, rf_channel,
                      ARRAY_SIZE(rf_channel));
    if (ret)
        return ret;
    ret = mt7601u_write_reg_pairs(dev, 0, rf_vga, ARRAY_SIZE(rf_vga));
    if (ret)
        return ret;
    ret = mt7601u_init_cal(dev);
    if (ret)
        return ret;
    dev->prev_pwr_diff = 100;
    INIT_DELAYED_WORK(&dev->cal_work, mt7601u_phy_calibrate);
    INIT_DELAYED_WORK(&dev->freq_cal.work, mt7601u_phy_freq_cal);
    return 0;
}
linux-bsp/drivers/mt7601u-sta/regs.h
New file
@@ -0,0 +1,639 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#ifndef __MT76_REGS_H
#define __MT76_REGS_H
#include <linux/bitops.h>
#ifndef GENMASK
#define GENMASK(h, l)       (((U32_C(1) << ((h) - (l) + 1)) - 1) << (l))
#endif
#define MT_ASIC_VERSION            0x0000
#define MT76XX_REV_E3        0x22
#define MT76XX_REV_E4        0x33
#define MT_CMB_CTRL            0x0020
#define MT_CMB_CTRL_XTAL_RDY        BIT(22)
#define MT_CMB_CTRL_PLL_LD        BIT(23)
#define MT_EFUSE_CTRL            0x0024
#define MT_EFUSE_CTRL_AOUT        GENMASK(5, 0)
#define MT_EFUSE_CTRL_MODE        GENMASK(7, 6)
#define MT_EFUSE_CTRL_LDO_OFF_TIME    GENMASK(13, 8)
#define MT_EFUSE_CTRL_LDO_ON_TIME    GENMASK(15, 14)
#define MT_EFUSE_CTRL_AIN        GENMASK(25, 16)
#define MT_EFUSE_CTRL_KICK        BIT(30)
#define MT_EFUSE_CTRL_SEL        BIT(31)
#define MT_EFUSE_DATA_BASE        0x0028
#define MT_EFUSE_DATA(_n)        (MT_EFUSE_DATA_BASE + ((_n) << 2))
#define MT_COEXCFG0            0x0040
#define MT_COEXCFG0_COEX_EN        BIT(0)
#define MT_WLAN_FUN_CTRL        0x0080
#define MT_WLAN_FUN_CTRL_WLAN_EN    BIT(0)
#define MT_WLAN_FUN_CTRL_WLAN_CLK_EN    BIT(1)
#define MT_WLAN_FUN_CTRL_WLAN_RESET_RF    BIT(2)
#define MT_WLAN_FUN_CTRL_WLAN_RESET    BIT(3) /* MT76x0 */
#define MT_WLAN_FUN_CTRL_CSR_F20M_CKEN    BIT(3) /* MT76x2 */
#define MT_WLAN_FUN_CTRL_PCIE_CLK_REQ    BIT(4)
#define MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL    BIT(5)
#define MT_WLAN_FUN_CTRL_INV_ANT_SEL    BIT(6)
#define MT_WLAN_FUN_CTRL_WAKE_HOST    BIT(7)
#define MT_WLAN_FUN_CTRL_THERM_RST    BIT(8) /* MT76x2 */
#define MT_WLAN_FUN_CTRL_THERM_CKEN    BIT(9) /* MT76x2 */
#define MT_WLAN_FUN_CTRL_GPIO_IN    GENMASK(15, 8) /* MT76x0 */
#define MT_WLAN_FUN_CTRL_GPIO_OUT    GENMASK(23, 16) /* MT76x0 */
#define MT_WLAN_FUN_CTRL_GPIO_OUT_EN    GENMASK(31, 24) /* MT76x0 */
#define MT_XO_CTRL0            0x0100
#define MT_XO_CTRL1            0x0104
#define MT_XO_CTRL2            0x0108
#define MT_XO_CTRL3            0x010c
#define MT_XO_CTRL4            0x0110
#define MT_XO_CTRL5            0x0114
#define MT_XO_CTRL5_C2_VAL        GENMASK(14, 8)
#define MT_XO_CTRL6            0x0118
#define MT_XO_CTRL6_C2_CTRL        GENMASK(14, 8)
#define MT_XO_CTRL7            0x011c
#define MT_WLAN_MTC_CTRL        0x10148
#define MT_WLAN_MTC_CTRL_MTCMOS_PWR_UP    BIT(0)
#define MT_WLAN_MTC_CTRL_PWR_ACK    BIT(12)
#define MT_WLAN_MTC_CTRL_PWR_ACK_S    BIT(13)
#define MT_WLAN_MTC_CTRL_BBP_MEM_PD    GENMASK(19, 16)
#define MT_WLAN_MTC_CTRL_PBF_MEM_PD    BIT(20)
#define MT_WLAN_MTC_CTRL_FCE_MEM_PD    BIT(21)
#define MT_WLAN_MTC_CTRL_TSO_MEM_PD    BIT(22)
#define MT_WLAN_MTC_CTRL_BBP_MEM_RB    BIT(24)
#define MT_WLAN_MTC_CTRL_PBF_MEM_RB    BIT(25)
#define MT_WLAN_MTC_CTRL_FCE_MEM_RB    BIT(26)
#define MT_WLAN_MTC_CTRL_TSO_MEM_RB    BIT(27)
#define MT_WLAN_MTC_CTRL_STATE_UP    BIT(28)
#define MT_INT_SOURCE_CSR        0x0200
#define MT_INT_MASK_CSR            0x0204
#define MT_INT_RX_DONE(_n)        BIT(_n)
#define MT_INT_RX_DONE_ALL        GENMASK(1, 0)
#define MT_INT_TX_DONE_ALL        GENMASK(13, 4)
#define MT_INT_TX_DONE(_n)        BIT(_n + 4)
#define MT_INT_RX_COHERENT        BIT(16)
#define MT_INT_TX_COHERENT        BIT(17)
#define MT_INT_ANY_COHERENT        BIT(18)
#define MT_INT_MCU_CMD            BIT(19)
#define MT_INT_TBTT            BIT(20)
#define MT_INT_PRE_TBTT            BIT(21)
#define MT_INT_TX_STAT            BIT(22)
#define MT_INT_AUTO_WAKEUP        BIT(23)
#define MT_INT_GPTIMER            BIT(24)
#define MT_INT_RXDELAYINT        BIT(26)
#define MT_INT_TXDELAYINT        BIT(27)
#define MT_WPDMA_GLO_CFG        0x0208
#define MT_WPDMA_GLO_CFG_TX_DMA_EN    BIT(0)
#define MT_WPDMA_GLO_CFG_TX_DMA_BUSY    BIT(1)
#define MT_WPDMA_GLO_CFG_RX_DMA_EN    BIT(2)
#define MT_WPDMA_GLO_CFG_RX_DMA_BUSY    BIT(3)
#define MT_WPDMA_GLO_CFG_DMA_BURST_SIZE    GENMASK(5, 4)
#define MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE    BIT(6)
#define MT_WPDMA_GLO_CFG_BIG_ENDIAN    BIT(7)
#define MT_WPDMA_GLO_CFG_HDR_SEG_LEN    GENMASK(15, 8)
#define MT_WPDMA_GLO_CFG_CLK_GATE_DIS    BIT(30)
#define MT_WPDMA_GLO_CFG_RX_2B_OFFSET    BIT(31)
#define MT_WPDMA_RST_IDX        0x020c
#define MT_WPDMA_DELAY_INT_CFG        0x0210
#define MT_WMM_AIFSN        0x0214
#define MT_WMM_AIFSN_MASK        GENMASK(3, 0)
#define MT_WMM_AIFSN_SHIFT(_n)        ((_n) * 4)
#define MT_WMM_CWMIN        0x0218
#define MT_WMM_CWMIN_MASK        GENMASK(3, 0)
#define MT_WMM_CWMIN_SHIFT(_n)        ((_n) * 4)
#define MT_WMM_CWMAX        0x021c
#define MT_WMM_CWMAX_MASK        GENMASK(3, 0)
#define MT_WMM_CWMAX_SHIFT(_n)        ((_n) * 4)
#define MT_WMM_TXOP_BASE        0x0220
#define MT_WMM_TXOP(_n)            (MT_WMM_TXOP_BASE + (((_n) / 2) << 2))
#define MT_WMM_TXOP_SHIFT(_n)        ((_n & 1) * 16)
#define MT_WMM_TXOP_MASK        GENMASK(15, 0)
#define MT_FCE_DMA_ADDR            0x0230
#define MT_FCE_DMA_LEN            0x0234
#define MT_USB_DMA_CFG            0x238
#define MT_USB_DMA_CFG_RX_BULK_AGG_TOUT    GENMASK(7, 0)
#define MT_USB_DMA_CFG_RX_BULK_AGG_LMT    GENMASK(15, 8)
#define MT_USB_DMA_CFG_PHY_CLR        BIT(16)
#define MT_USB_DMA_CFG_TX_CLR        BIT(19)
#define MT_USB_DMA_CFG_TXOP_HALT    BIT(20)
#define MT_USB_DMA_CFG_RX_BULK_AGG_EN    BIT(21)
#define MT_USB_DMA_CFG_RX_BULK_EN    BIT(22)
#define MT_USB_DMA_CFG_TX_BULK_EN    BIT(23)
#define MT_USB_DMA_CFG_UDMA_RX_WL_DROP    BIT(25)
#define MT_USB_DMA_CFG_EP_OUT_VALID    GENMASK(29, 27)
#define MT_USB_DMA_CFG_RX_BUSY        BIT(30)
#define MT_USB_DMA_CFG_TX_BUSY        BIT(31)
#define MT_TSO_CTRL            0x0250
#define MT_HEADER_TRANS_CTRL_REG    0x0260
#define MT_US_CYC_CFG            0x02a4
#define MT_US_CYC_CNT            GENMASK(7, 0)
#define MT_TX_RING_BASE            0x0300
#define MT_RX_RING_BASE            0x03c0
#define MT_RING_SIZE            0x10
#define MT_TX_HW_QUEUE_MCU        8
#define MT_TX_HW_QUEUE_MGMT        9
#define MT_PBF_SYS_CTRL            0x0400
#define MT_PBF_SYS_CTRL_MCU_RESET    BIT(0)
#define MT_PBF_SYS_CTRL_DMA_RESET    BIT(1)
#define MT_PBF_SYS_CTRL_MAC_RESET    BIT(2)
#define MT_PBF_SYS_CTRL_PBF_RESET    BIT(3)
#define MT_PBF_SYS_CTRL_ASY_RESET    BIT(4)
#define MT_PBF_CFG            0x0404
#define MT_PBF_CFG_TX0Q_EN        BIT(0)
#define MT_PBF_CFG_TX1Q_EN        BIT(1)
#define MT_PBF_CFG_TX2Q_EN        BIT(2)
#define MT_PBF_CFG_TX3Q_EN        BIT(3)
#define MT_PBF_CFG_RX0Q_EN        BIT(4)
#define MT_PBF_CFG_RX_DROP_EN        BIT(8)
#define MT_PBF_TX_MAX_PCNT        0x0408
#define MT_PBF_RX_MAX_PCNT        0x040c
#define MT_BCN_OFFSET_BASE        0x041c
#define MT_BCN_OFFSET(_n)        (MT_BCN_OFFSET_BASE + ((_n) << 2))
#define MT_RXQ_STA            0x0430
#define MT_TXQ_STA            0x0434
#define    MT_RF_CSR_CFG            0x0500
#define MT_RF_CSR_CFG_DATA        GENMASK(7, 0)
#define MT_RF_CSR_CFG_REG_ID        GENMASK(13, 8)
#define MT_RF_CSR_CFG_REG_BANK        GENMASK(17, 14)
#define MT_RF_CSR_CFG_WR        BIT(30)
#define MT_RF_CSR_CFG_KICK        BIT(31)
#define MT_RF_BYPASS_0            0x0504
#define MT_RF_BYPASS_1            0x0508
#define MT_RF_SETTING_0            0x050c
#define MT_RF_DATA_WRITE        0x0524
#define MT_RF_CTRL            0x0528
#define MT_RF_CTRL_ADDR            GENMASK(11, 0)
#define MT_RF_CTRL_WRITE        BIT(12)
#define MT_RF_CTRL_BUSY            BIT(13)
#define MT_RF_CTRL_IDX            BIT(16)
#define MT_RF_DATA_READ            0x052c
#define MT_FCE_PSE_CTRL            0x0800
#define MT_FCE_PARAMETERS        0x0804
#define MT_FCE_CSO            0x0808
#define MT_FCE_L2_STUFF            0x080c
#define MT_FCE_L2_STUFF_HT_L2_EN    BIT(0)
#define MT_FCE_L2_STUFF_QOS_L2_EN    BIT(1)
#define MT_FCE_L2_STUFF_RX_STUFF_EN    BIT(2)
#define MT_FCE_L2_STUFF_TX_STUFF_EN    BIT(3)
#define MT_FCE_L2_STUFF_WR_MPDU_LEN_EN    BIT(4)
#define MT_FCE_L2_STUFF_MVINV_BSWAP    BIT(5)
#define MT_FCE_L2_STUFF_TS_CMD_QSEL_EN    GENMASK(15, 8)
#define MT_FCE_L2_STUFF_TS_LEN_EN    GENMASK(23, 16)
#define MT_FCE_L2_STUFF_OTHER_PORT    GENMASK(25, 24)
#define MT_FCE_WLAN_FLOW_CONTROL1    0x0824
#define MT_TX_CPU_FROM_FCE_BASE_PTR    0x09a0
#define MT_TX_CPU_FROM_FCE_MAX_COUNT    0x09a4
#define MT_TX_CPU_FROM_FCE_CPU_DESC_IDX    0x09a8
#define MT_FCE_PDMA_GLOBAL_CONF        0x09c4
#define MT_PAUSE_ENABLE_CONTROL1    0x0a38
#define MT_FCE_SKIP_FS            0x0a6c
#define MT_MAC_CSR0            0x1000
#define MT_MAC_SYS_CTRL            0x1004
#define MT_MAC_SYS_CTRL_RESET_CSR    BIT(0)
#define MT_MAC_SYS_CTRL_RESET_BBP    BIT(1)
#define MT_MAC_SYS_CTRL_ENABLE_TX    BIT(2)
#define MT_MAC_SYS_CTRL_ENABLE_RX    BIT(3)
#define MT_MAC_ADDR_DW0            0x1008
#define MT_MAC_ADDR_DW1            0x100c
#define MT_MAC_ADDR_DW1_U2ME_MASK    GENMASK(23, 16)
#define MT_MAC_BSSID_DW0        0x1010
#define MT_MAC_BSSID_DW1        0x1014
#define MT_MAC_BSSID_DW1_ADDR        GENMASK(15, 0)
#define MT_MAC_BSSID_DW1_MBSS_MODE    GENMASK(17, 16)
#define MT_MAC_BSSID_DW1_MBEACON_N    GENMASK(20, 18)
#define MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT    BIT(21)
#define MT_MAC_BSSID_DW1_MBSS_MODE_B2    BIT(22)
#define MT_MAC_BSSID_DW1_MBEACON_N_B3    BIT(23)
#define MT_MAC_BSSID_DW1_MBSS_IDX_BYTE    GENMASK(26, 24)
#define MT_MAX_LEN_CFG            0x1018
#define MT_MAX_LEN_CFG_AMPDU        GENMASK(13, 12)
#define MT_BBP_CSR_CFG            0x101c
#define MT_BBP_CSR_CFG_VAL        GENMASK(7, 0)
#define MT_BBP_CSR_CFG_REG_NUM        GENMASK(15, 8)
#define MT_BBP_CSR_CFG_READ        BIT(16)
#define MT_BBP_CSR_CFG_BUSY        BIT(17)
#define MT_BBP_CSR_CFG_PAR_DUR        BIT(18)
#define MT_BBP_CSR_CFG_RW_MODE        BIT(19)
#define MT_AMPDU_MAX_LEN_20M1S        0x1030
#define MT_AMPDU_MAX_LEN_20M2S        0x1034
#define MT_AMPDU_MAX_LEN_40M1S        0x1038
#define MT_AMPDU_MAX_LEN_40M2S        0x103c
#define MT_AMPDU_MAX_LEN        0x1040
#define MT_WCID_DROP_BASE        0x106c
#define MT_WCID_DROP(_n)        (MT_WCID_DROP_BASE + ((_n) >> 5) * 4)
#define MT_WCID_DROP_MASK(_n)        BIT((_n) % 32)
#define MT_BCN_BYPASS_MASK        0x108c
#define MT_MAC_APC_BSSID_BASE        0x1090
#define MT_MAC_APC_BSSID_L(_n)        (MT_MAC_APC_BSSID_BASE + ((_n) * 8))
#define MT_MAC_APC_BSSID_H(_n)        (MT_MAC_APC_BSSID_BASE + ((_n) * 8 + 4))
#define MT_MAC_APC_BSSID_H_ADDR        GENMASK(15, 0)
#define MT_MAC_APC_BSSID0_H_EN        BIT(16)
#define MT_XIFS_TIME_CFG        0x1100
#define MT_XIFS_TIME_CFG_CCK_SIFS    GENMASK(7, 0)
#define MT_XIFS_TIME_CFG_OFDM_SIFS    GENMASK(15, 8)
#define MT_XIFS_TIME_CFG_OFDM_XIFS    GENMASK(19, 16)
#define MT_XIFS_TIME_CFG_EIFS        GENMASK(28, 20)
#define MT_XIFS_TIME_CFG_BB_RXEND_EN    BIT(29)
#define MT_BKOFF_SLOT_CFG        0x1104
#define MT_BKOFF_SLOT_CFG_SLOTTIME    GENMASK(7, 0)
#define MT_BKOFF_SLOT_CFG_CC_DELAY    GENMASK(11, 8)
#define MT_BEACON_TIME_CFG        0x1114
#define MT_BEACON_TIME_CFG_INTVAL    GENMASK(15, 0)
#define MT_BEACON_TIME_CFG_TIMER_EN    BIT(16)
#define MT_BEACON_TIME_CFG_SYNC_MODE    GENMASK(18, 17)
#define MT_BEACON_TIME_CFG_TBTT_EN    BIT(19)
#define MT_BEACON_TIME_CFG_BEACON_TX    BIT(20)
#define MT_BEACON_TIME_CFG_TSF_COMP    GENMASK(31, 24)
#define MT_TBTT_SYNC_CFG        0x1118
#define MT_TBTT_TIMER_CFG        0x1124
#define MT_INT_TIMER_CFG        0x1128
#define MT_INT_TIMER_CFG_PRE_TBTT    GENMASK(15, 0)
#define MT_INT_TIMER_CFG_GP_TIMER    GENMASK(31, 16)
#define MT_INT_TIMER_EN            0x112c
#define MT_INT_TIMER_EN_PRE_TBTT_EN    BIT(0)
#define MT_INT_TIMER_EN_GP_TIMER_EN    BIT(1)
#define MT_MAC_STATUS            0x1200
#define MT_MAC_STATUS_TX        BIT(0)
#define MT_MAC_STATUS_RX        BIT(1)
#define MT_PWR_PIN_CFG            0x1204
#define MT_AUX_CLK_CFG            0x120c
#define MT_BB_PA_MODE_CFG0        0x1214
#define MT_BB_PA_MODE_CFG1        0x1218
#define MT_RF_PA_MODE_CFG0        0x121c
#define MT_RF_PA_MODE_CFG1        0x1220
#define MT_RF_PA_MODE_ADJ0        0x1228
#define MT_RF_PA_MODE_ADJ1        0x122c
#define MT_DACCLK_EN_DLY_CFG        0x1264
#define MT_EDCA_CFG_BASE        0x1300
#define MT_EDCA_CFG_AC(_n)        (MT_EDCA_CFG_BASE + ((_n) << 2))
#define MT_EDCA_CFG_TXOP        GENMASK(7, 0)
#define MT_EDCA_CFG_AIFSN        GENMASK(11, 8)
#define MT_EDCA_CFG_CWMIN        GENMASK(15, 12)
#define MT_EDCA_CFG_CWMAX        GENMASK(19, 16)
#define MT_TX_PWR_CFG_0            0x1314
#define MT_TX_PWR_CFG_1            0x1318
#define MT_TX_PWR_CFG_2            0x131c
#define MT_TX_PWR_CFG_3            0x1320
#define MT_TX_PWR_CFG_4            0x1324
#define MT_TX_BAND_CFG            0x132c
#define MT_TX_BAND_CFG_UPPER_40M    BIT(0)
#define MT_TX_BAND_CFG_5G        BIT(1)
#define MT_TX_BAND_CFG_2G        BIT(2)
#define MT_HT_FBK_TO_LEGACY        0x1384
#define MT_TX_MPDU_ADJ_INT        0x1388
#define MT_TX_PWR_CFG_7            0x13d4
#define MT_TX_PWR_CFG_8            0x13d8
#define MT_TX_PWR_CFG_9            0x13dc
#define MT_TX_SW_CFG0            0x1330
#define MT_TX_SW_CFG1            0x1334
#define MT_TX_SW_CFG2            0x1338
#define MT_TXOP_CTRL_CFG        0x1340
#define MT_TXOP_TRUN_EN            GENMASK(5, 0)
#define MT_TXOP_EXT_CCA_DLY        GENMASK(15, 8)
#define MT_TXOP_CTRL
#define MT_TX_RTS_CFG            0x1344
#define MT_TX_RTS_CFG_RETRY_LIMIT    GENMASK(7, 0)
#define MT_TX_RTS_CFG_THRESH        GENMASK(23, 8)
#define MT_TX_RTS_FALLBACK        BIT(24)
#define MT_TX_TIMEOUT_CFG        0x1348
#define MT_TX_RETRY_CFG            0x134c
#define MT_TX_LINK_CFG            0x1350
#define MT_HT_FBK_CFG0            0x1354
#define MT_HT_FBK_CFG1            0x1358
#define MT_LG_FBK_CFG0            0x135c
#define MT_LG_FBK_CFG1            0x1360
#define MT_CCK_PROT_CFG            0x1364
#define MT_OFDM_PROT_CFG        0x1368
#define MT_MM20_PROT_CFG        0x136c
#define MT_MM40_PROT_CFG        0x1370
#define MT_GF20_PROT_CFG        0x1374
#define MT_GF40_PROT_CFG        0x1378
#define MT_PROT_RATE            GENMASK(15, 0)
#define MT_PROT_CTRL_RTS_CTS        BIT(16)
#define MT_PROT_CTRL_CTS2SELF        BIT(17)
#define MT_PROT_NAV_SHORT        BIT(18)
#define MT_PROT_NAV_LONG        BIT(19)
#define MT_PROT_TXOP_ALLOW_CCK        BIT(20)
#define MT_PROT_TXOP_ALLOW_OFDM        BIT(21)
#define MT_PROT_TXOP_ALLOW_MM20        BIT(22)
#define MT_PROT_TXOP_ALLOW_MM40        BIT(23)
#define MT_PROT_TXOP_ALLOW_GF20        BIT(24)
#define MT_PROT_TXOP_ALLOW_GF40        BIT(25)
#define MT_PROT_RTS_THR_EN        BIT(26)
#define MT_PROT_RATE_CCK_11        0x0003
#define MT_PROT_RATE_OFDM_6        0x4000
#define MT_PROT_RATE_OFDM_24        0x4004
#define MT_PROT_RATE_DUP_OFDM_24    0x4084
#define MT_PROT_TXOP_ALLOW_ALL        GENMASK(25, 20)
#define MT_PROT_TXOP_ALLOW_BW20        (MT_PROT_TXOP_ALLOW_ALL &    \
                     ~MT_PROT_TXOP_ALLOW_MM40 &    \
                     ~MT_PROT_TXOP_ALLOW_GF40)
#define MT_EXP_ACK_TIME            0x1380
#define MT_TX_PWR_CFG_0_EXT        0x1390
#define MT_TX_PWR_CFG_1_EXT        0x1394
#define MT_TX_FBK_LIMIT            0x1398
#define MT_TX_FBK_LIMIT_MPDU_FBK    GENMASK(7, 0)
#define MT_TX_FBK_LIMIT_AMPDU_FBK    GENMASK(15, 8)
#define MT_TX_FBK_LIMIT_MPDU_UP_CLEAR    BIT(16)
#define MT_TX_FBK_LIMIT_AMPDU_UP_CLEAR    BIT(17)
#define MT_TX_FBK_LIMIT_RATE_LUT    BIT(18)
#define MT_TX0_RF_GAIN_CORR        0x13a0
#define MT_TX1_RF_GAIN_CORR        0x13a4
#define MT_TX0_RF_GAIN_ATTEN        0x13a8
#define MT_TX_ALC_CFG_0            0x13b0
#define MT_TX_ALC_CFG_0_CH_INIT_0    GENMASK(5, 0)
#define MT_TX_ALC_CFG_0_CH_INIT_1    GENMASK(13, 8)
#define MT_TX_ALC_CFG_0_LIMIT_0        GENMASK(21, 16)
#define MT_TX_ALC_CFG_0_LIMIT_1        GENMASK(29, 24)
#define MT_TX_ALC_CFG_1            0x13b4
#define MT_TX_ALC_CFG_1_TEMP_COMP    GENMASK(5, 0)
#define MT_TX_ALC_CFG_2            0x13a8
#define MT_TX_ALC_CFG_2_TEMP_COMP    GENMASK(5, 0)
#define MT_TX0_BB_GAIN_ATTEN        0x13c0
#define MT_TX_ALC_VGA3            0x13c8
#define MT_TX_PROT_CFG6            0x13e0
#define MT_TX_PROT_CFG7            0x13e4
#define MT_TX_PROT_CFG8            0x13e8
#define MT_PIFS_TX_CFG            0x13ec
#define MT_RX_FILTR_CFG            0x1400
#define MT_RX_FILTR_CFG_CRC_ERR        BIT(0)
#define MT_RX_FILTR_CFG_PHY_ERR        BIT(1)
#define MT_RX_FILTR_CFG_PROMISC        BIT(2)
#define MT_RX_FILTR_CFG_OTHER_BSS    BIT(3)
#define MT_RX_FILTR_CFG_VER_ERR        BIT(4)
#define MT_RX_FILTR_CFG_MCAST        BIT(5)
#define MT_RX_FILTR_CFG_BCAST        BIT(6)
#define MT_RX_FILTR_CFG_DUP        BIT(7)
#define MT_RX_FILTR_CFG_CFACK        BIT(8)
#define MT_RX_FILTR_CFG_CFEND        BIT(9)
#define MT_RX_FILTR_CFG_ACK        BIT(10)
#define MT_RX_FILTR_CFG_CTS        BIT(11)
#define MT_RX_FILTR_CFG_RTS        BIT(12)
#define MT_RX_FILTR_CFG_PSPOLL        BIT(13)
#define MT_RX_FILTR_CFG_BA        BIT(14)
#define MT_RX_FILTR_CFG_BAR        BIT(15)
#define MT_RX_FILTR_CFG_CTRL_RSV    BIT(16)
#define MT_AUTO_RSP_CFG            0x1404
#define MT_AUTO_RSP_PREAMB_SHORT    BIT(4)
#define MT_LEGACY_BASIC_RATE        0x1408
#define MT_HT_BASIC_RATE        0x140c
#define MT_RX_PARSER_CFG        0x1418
#define MT_RX_PARSER_RX_SET_NAV_ALL    BIT(0)
#define MT_EXT_CCA_CFG            0x141c
#define MT_EXT_CCA_CFG_CCA0        GENMASK(1, 0)
#define MT_EXT_CCA_CFG_CCA1        GENMASK(3, 2)
#define MT_EXT_CCA_CFG_CCA2        GENMASK(5, 4)
#define MT_EXT_CCA_CFG_CCA3        GENMASK(7, 6)
#define MT_EXT_CCA_CFG_CCA_MASK        GENMASK(11, 8)
#define MT_EXT_CCA_CFG_ED_CCA_MASK    GENMASK(15, 12)
#define MT_TX_SW_CFG3            0x1478
#define MT_PN_PAD_MODE            0x150c
#define MT_TXOP_HLDR_ET            0x1608
#define MT_PROT_AUTO_TX_CFG        0x1648
#define MT_RX_STA_CNT0            0x1700
#define MT_RX_STA_CNT1            0x1704
#define MT_RX_STA_CNT2            0x1708
#define MT_TX_STA_CNT0            0x170c
#define MT_TX_STA_CNT1            0x1710
#define MT_TX_STA_CNT2            0x1714
/* Vendor driver defines content of the second word of STAT_FIFO as follows:
 *    MT_TX_STAT_FIFO_RATE        GENMASK(26, 16)
 *    MT_TX_STAT_FIFO_ETXBF        BIT(27)
 *    MT_TX_STAT_FIFO_SND        BIT(28)
 *    MT_TX_STAT_FIFO_ITXBF        BIT(29)
 * However, tests show that b16-31 have the same layout as TXWI rate_ctl
 * with rate set to rate at which frame was acked.
 */
#define MT_TX_STAT_FIFO            0x1718
#define MT_TX_STAT_FIFO_VALID        BIT(0)
#define MT_TX_STAT_FIFO_PID_TYPE    GENMASK(4, 1)
#define MT_TX_STAT_FIFO_SUCCESS        BIT(5)
#define MT_TX_STAT_FIFO_AGGR        BIT(6)
#define MT_TX_STAT_FIFO_ACKREQ        BIT(7)
#define MT_TX_STAT_FIFO_WCID        GENMASK(15, 8)
#define MT_TX_STAT_FIFO_RATE        GENMASK(31, 16)
#define MT_TX_AGG_STAT            0x171c
#define MT_TX_AGG_CNT_BASE0        0x1720
#define MT_MPDU_DENSITY_CNT        0x1740
#define MT_TX_AGG_CNT_BASE1        0x174c
#define MT_TX_AGG_CNT(_id)        ((_id) < 8 ?            \
                     MT_TX_AGG_CNT_BASE0 + ((_id) << 2) : \
                     MT_TX_AGG_CNT_BASE1 + ((_id - 8) << 2))
#define MT_TX_STAT_FIFO_EXT        0x1798
#define MT_TX_STAT_FIFO_EXT_RETRY    GENMASK(7, 0)
#define MT_BBP_CORE_BASE        0x2000
#define MT_BBP_IBI_BASE            0x2100
#define MT_BBP_AGC_BASE            0x2300
#define MT_BBP_TXC_BASE            0x2400
#define MT_BBP_RXC_BASE            0x2500
#define MT_BBP_TXO_BASE            0x2600
#define MT_BBP_TXBE_BASE        0x2700
#define MT_BBP_RXFE_BASE        0x2800
#define MT_BBP_RXO_BASE            0x2900
#define MT_BBP_DFS_BASE            0x2a00
#define MT_BBP_TR_BASE            0x2b00
#define MT_BBP_CAL_BASE            0x2c00
#define MT_BBP_DSC_BASE            0x2e00
#define MT_BBP_PFMU_BASE        0x2f00
#define MT_BBP(_type, _n)        (MT_BBP_##_type##_BASE + ((_n) << 2))
#define MT_BBP_CORE_R1_BW        GENMASK(4, 3)
#define MT_BBP_AGC_R0_CTRL_CHAN        GENMASK(9, 8)
#define MT_BBP_AGC_R0_BW        GENMASK(14, 12)
/* AGC, R4/R5 */
#define MT_BBP_AGC_LNA_GAIN        GENMASK(21, 16)
/* AGC, R8/R9 */
#define MT_BBP_AGC_GAIN            GENMASK(14, 8)
#define MT_BBP_AGC20_RSSI0        GENMASK(7, 0)
#define MT_BBP_AGC20_RSSI1        GENMASK(15, 8)
#define MT_BBP_TXBE_R0_CTRL_CHAN    GENMASK(1, 0)
#define MT_WCID_ADDR_BASE        0x1800
#define MT_WCID_ADDR(_n)        (MT_WCID_ADDR_BASE + (_n) * 8)
#define MT_SRAM_BASE            0x4000
#define MT_WCID_KEY_BASE        0x8000
#define MT_WCID_KEY(_n)            (MT_WCID_KEY_BASE + (_n) * 32)
#define MT_WCID_IV_BASE            0xa000
#define MT_WCID_IV(_n)            (MT_WCID_IV_BASE + (_n) * 8)
#define MT_WCID_ATTR_BASE        0xa800
#define MT_WCID_ATTR(_n)        (MT_WCID_ATTR_BASE + (_n) * 4)
#define MT_WCID_ATTR_PAIRWISE        BIT(0)
#define MT_WCID_ATTR_PKEY_MODE        GENMASK(3, 1)
#define MT_WCID_ATTR_BSS_IDX        GENMASK(6, 4)
#define MT_WCID_ATTR_RXWI_UDF        GENMASK(9, 7)
#define MT_WCID_ATTR_PKEY_MODE_EXT    BIT(10)
#define MT_WCID_ATTR_BSS_IDX_EXT    BIT(11)
#define MT_WCID_ATTR_WAPI_MCBC        BIT(15)
#define MT_WCID_ATTR_WAPI_KEYID        GENMASK(31, 24)
#define MT_SKEY_BASE_0            0xac00
#define MT_SKEY_BASE_1            0xb400
#define MT_SKEY_0(_bss, _idx)        \
    (MT_SKEY_BASE_0 + (4 * (_bss) + _idx) * 32)
#define MT_SKEY_1(_bss, _idx)        \
    (MT_SKEY_BASE_1 + (4 * ((_bss) & 7) + _idx) * 32)
#define MT_SKEY(_bss, _idx)        \
    ((_bss & 8) ? MT_SKEY_1(_bss, _idx) : MT_SKEY_0(_bss, _idx))
#define MT_SKEY_MODE_BASE_0        0xb000
#define MT_SKEY_MODE_BASE_1        0xb3f0
#define MT_SKEY_MODE_0(_bss)        \
    (MT_SKEY_MODE_BASE_0 + ((_bss / 2) << 2))
#define MT_SKEY_MODE_1(_bss)        \
    (MT_SKEY_MODE_BASE_1 + ((((_bss) & 7) / 2) << 2))
#define MT_SKEY_MODE(_bss)        \
    ((_bss & 8) ? MT_SKEY_MODE_1(_bss) : MT_SKEY_MODE_0(_bss))
#define MT_SKEY_MODE_MASK        GENMASK(3, 0)
#define MT_SKEY_MODE_SHIFT(_bss, _idx)    (4 * ((_idx) + 4 * (_bss & 1)))
#define MT_BEACON_BASE            0xc000
#define MT_TEMP_SENSOR            0x1d000
#define MT_TEMP_SENSOR_VAL        GENMASK(6, 0)
enum mt76_cipher_type {
    MT_CIPHER_NONE,
    MT_CIPHER_WEP40,
    MT_CIPHER_WEP104,
    MT_CIPHER_TKIP,
    MT_CIPHER_AES_CCMP,
    MT_CIPHER_CKIP40,
    MT_CIPHER_CKIP104,
    MT_CIPHER_CKIP128,
    MT_CIPHER_WAPI,
};
#endif
linux-bsp/drivers/mt7601u-sta/trace.c
New file
@@ -0,0 +1,21 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#include <linux/module.h>
#ifndef __CHECKER__
#define CREATE_TRACE_POINTS
#include "trace.h"
#endif
linux-bsp/drivers/mt7601u-sta/trace.h
New file
@@ -0,0 +1,400 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#if !defined(__MT7601U_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
#define __MT7601U_TRACE_H
#include <linux/tracepoint.h>
#include "mt7601u.h"
#include "mac.h"
#undef TRACE_SYSTEM
#define TRACE_SYSTEM mt7601u
#define MAXNAME        32
#define DEV_ENTRY    __array(char, wiphy_name, 32)
#define DEV_ASSIGN    strlcpy(__entry->wiphy_name,            \
                wiphy_name(dev->hw->wiphy), MAXNAME)
#define DEV_PR_FMT    "%s "
#define DEV_PR_ARG    __entry->wiphy_name
#define REG_ENTRY    __field(u32, reg) __field(u32, val)
#define REG_ASSIGN    __entry->reg = reg; __entry->val = val
#define REG_PR_FMT    "%04x=%08x"
#define REG_PR_ARG    __entry->reg, __entry->val
DECLARE_EVENT_CLASS(dev_reg_evt,
    TP_PROTO(struct mt7601u_dev *dev, u32 reg, u32 val),
    TP_ARGS(dev, reg, val),
    TP_STRUCT__entry(
        DEV_ENTRY
        REG_ENTRY
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        REG_ASSIGN;
    ),
    TP_printk(
        DEV_PR_FMT REG_PR_FMT,
        DEV_PR_ARG, REG_PR_ARG
    )
);
DEFINE_EVENT(dev_reg_evt, reg_read,
    TP_PROTO(struct mt7601u_dev *dev, u32 reg, u32 val),
    TP_ARGS(dev, reg, val)
);
DEFINE_EVENT(dev_reg_evt, reg_write,
    TP_PROTO(struct mt7601u_dev *dev, u32 reg, u32 val),
    TP_ARGS(dev, reg, val)
);
TRACE_EVENT(mt_submit_urb,
    TP_PROTO(struct mt7601u_dev *dev, struct urb *u),
    TP_ARGS(dev, u),
    TP_STRUCT__entry(
        DEV_ENTRY __field(unsigned, pipe) __field(u32, len)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        __entry->pipe = u->pipe;
        __entry->len = u->transfer_buffer_length;
    ),
    TP_printk(DEV_PR_FMT "p:%08x len:%u",
          DEV_PR_ARG, __entry->pipe, __entry->len)
);
#define trace_mt_submit_urb_sync(__dev, __pipe, __len) ({    \
    struct urb u;                    \
    u.pipe = __pipe;                \
    u.transfer_buffer_length = __len;        \
    trace_mt_submit_urb(__dev, &u);            \
})
TRACE_EVENT(mt_mcu_msg_send,
    TP_PROTO(struct mt7601u_dev *dev,
         struct sk_buff *skb, u32 csum, bool resp),
    TP_ARGS(dev, skb, csum, resp),
    TP_STRUCT__entry(
        DEV_ENTRY
        __field(u32, info)
        __field(u32, csum)
        __field(bool, resp)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        __entry->info = *(u32 *)skb->data;
        __entry->csum = csum;
        __entry->resp = resp;
    ),
    TP_printk(DEV_PR_FMT "i:%08x c:%08x r:%d",
          DEV_PR_ARG, __entry->info, __entry->csum, __entry->resp)
);
TRACE_EVENT(mt_vend_req,
    TP_PROTO(struct mt7601u_dev *dev, unsigned pipe, u8 req, u8 req_type,
         u16 val, u16 offset, void *buf, size_t buflen, int ret),
    TP_ARGS(dev, pipe, req, req_type, val, offset, buf, buflen, ret),
    TP_STRUCT__entry(
        DEV_ENTRY
        __field(unsigned, pipe) __field(u8, req) __field(u8, req_type)
        __field(u16, val) __field(u16, offset) __field(void*, buf)
        __field(int, buflen) __field(int, ret)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        __entry->pipe = pipe;
        __entry->req = req;
        __entry->req_type = req_type;
        __entry->val = val;
        __entry->offset = offset;
        __entry->buf = buf;
        __entry->buflen = buflen;
        __entry->ret = ret;
    ),
    TP_printk(DEV_PR_FMT
          "%d p:%08x req:%02hhx %02hhx val:%04hx %04hx buf:%d %d",
          DEV_PR_ARG, __entry->ret, __entry->pipe, __entry->req,
          __entry->req_type, __entry->val, __entry->offset,
          !!__entry->buf, __entry->buflen)
);
TRACE_EVENT(ee_read,
    TP_PROTO(struct mt7601u_dev *dev, int offset, u16 val),
    TP_ARGS(dev, offset, val),
    TP_STRUCT__entry(
        DEV_ENTRY
        __field(int, o) __field(u16, v)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        __entry->o = offset;
        __entry->v = val;
    ),
    TP_printk(DEV_PR_FMT "%04x=%04x", DEV_PR_ARG, __entry->o, __entry->v)
);
DECLARE_EVENT_CLASS(dev_rf_reg_evt,
    TP_PROTO(struct mt7601u_dev *dev, u8 bank, u8 reg, u8 val),
    TP_ARGS(dev, bank, reg, val),
    TP_STRUCT__entry(
        DEV_ENTRY
        __field(u8, bank)
        __field(u8, reg)
        __field(u8, val)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        REG_ASSIGN;
        __entry->bank = bank;
    ),
    TP_printk(
        DEV_PR_FMT "%02hhx:%02hhx=%02hhx",
        DEV_PR_ARG, __entry->bank, __entry->reg, __entry->val
    )
);
DEFINE_EVENT(dev_rf_reg_evt, rf_read,
    TP_PROTO(struct mt7601u_dev *dev, u8 bank, u8 reg, u8 val),
    TP_ARGS(dev, bank, reg, val)
);
DEFINE_EVENT(dev_rf_reg_evt, rf_write,
    TP_PROTO(struct mt7601u_dev *dev, u8 bank, u8 reg, u8 val),
    TP_ARGS(dev, bank, reg, val)
);
DECLARE_EVENT_CLASS(dev_bbp_reg_evt,
    TP_PROTO(struct mt7601u_dev *dev, u8 reg, u8 val),
    TP_ARGS(dev, reg, val),
    TP_STRUCT__entry(
        DEV_ENTRY
        __field(u8, reg)
        __field(u8, val)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        REG_ASSIGN;
    ),
    TP_printk(
        DEV_PR_FMT "%02hhx=%02hhx",
        DEV_PR_ARG, __entry->reg, __entry->val
    )
);
DEFINE_EVENT(dev_bbp_reg_evt, bbp_read,
    TP_PROTO(struct mt7601u_dev *dev, u8 reg, u8 val),
    TP_ARGS(dev, reg, val)
);
DEFINE_EVENT(dev_bbp_reg_evt, bbp_write,
    TP_PROTO(struct mt7601u_dev *dev, u8 reg, u8 val),
    TP_ARGS(dev, reg, val)
);
DECLARE_EVENT_CLASS(dev_simple_evt,
    TP_PROTO(struct mt7601u_dev *dev, u8 val),
    TP_ARGS(dev, val),
    TP_STRUCT__entry(
        DEV_ENTRY
        __field(u8, val)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        __entry->val = val;
    ),
    TP_printk(
        DEV_PR_FMT "%02hhx", DEV_PR_ARG, __entry->val
    )
);
DEFINE_EVENT(dev_simple_evt, temp_mode,
    TP_PROTO(struct mt7601u_dev *dev, u8 val),
    TP_ARGS(dev, val)
);
DEFINE_EVENT(dev_simple_evt, read_temp,
    TP_PROTO(struct mt7601u_dev *dev, u8 val),
    TP_ARGS(dev, val)
);
DEFINE_EVENT(dev_simple_evt, freq_cal_adjust,
    TP_PROTO(struct mt7601u_dev *dev, u8 val),
    TP_ARGS(dev, val)
);
TRACE_EVENT(freq_cal_offset,
    TP_PROTO(struct mt7601u_dev *dev, u8 phy_mode, s8 freq_off),
    TP_ARGS(dev, phy_mode, freq_off),
    TP_STRUCT__entry(
        DEV_ENTRY
        __field(u8, phy_mode)
        __field(s8, freq_off)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        __entry->phy_mode = phy_mode;
        __entry->freq_off = freq_off;
    ),
    TP_printk(DEV_PR_FMT "phy:%02hhx off:%02hhx",
          DEV_PR_ARG, __entry->phy_mode, __entry->freq_off)
);
TRACE_EVENT(mt_rx,
    TP_PROTO(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi, u32 f),
    TP_ARGS(dev, rxwi, f),
    TP_STRUCT__entry(
        DEV_ENTRY
        __field_struct(struct mt7601u_rxwi, rxwi)
        __field(u32, fce_info)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        __entry->rxwi = *rxwi;
        __entry->fce_info = f;
    ),
    TP_printk(DEV_PR_FMT "rxi:%08x ctl:%08x frag_sn:%04hx rate:%04hx "
          "uknw:%02hhx z:%02hhx%02hhx%02hhx snr:%02hhx "
          "ant:%02hhx gain:%02hhx freq_o:%02hhx "
          "r:%08x ea:%08x fce:%08x", DEV_PR_ARG,
          le32_to_cpu(__entry->rxwi.rxinfo),
          le32_to_cpu(__entry->rxwi.ctl),
          le16_to_cpu(__entry->rxwi.frag_sn),
          le16_to_cpu(__entry->rxwi.rate),
          __entry->rxwi.unknown,
          __entry->rxwi.zero[0], __entry->rxwi.zero[1],
          __entry->rxwi.zero[2],
          __entry->rxwi.snr, __entry->rxwi.ant,
          __entry->rxwi.gain, __entry->rxwi.freq_off,
          __entry->rxwi.resv2, __entry->rxwi.expert_ant,
          __entry->fce_info)
);
TRACE_EVENT(mt_tx,
    TP_PROTO(struct mt7601u_dev *dev, struct sk_buff *skb,
         struct mt76_sta *sta, struct mt76_txwi *h),
    TP_ARGS(dev, skb, sta, h),
    TP_STRUCT__entry(
        DEV_ENTRY
        __field_struct(struct mt76_txwi, h)
        __field(struct sk_buff *, skb)
        __field(struct mt76_sta *, sta)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        __entry->h = *h;
        __entry->skb = skb;
        __entry->sta = sta;
    ),
    TP_printk(DEV_PR_FMT "skb:%p sta:%p  flg:%04hx rate_ctl:%04hx "
          "ack:%02hhx wcid:%02hhx len_ctl:%05hx", DEV_PR_ARG,
          __entry->skb, __entry->sta,
          le16_to_cpu(__entry->h.flags),
          le16_to_cpu(__entry->h.rate_ctl),
          __entry->h.ack_ctl, __entry->h.wcid,
          le16_to_cpu(__entry->h.len_ctl))
);
TRACE_EVENT(mt_tx_dma_done,
    TP_PROTO(struct mt7601u_dev *dev, struct sk_buff *skb),
    TP_ARGS(dev, skb),
    TP_STRUCT__entry(
        DEV_ENTRY
        __field(struct sk_buff *, skb)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        __entry->skb = skb;
    ),
    TP_printk(DEV_PR_FMT "%p", DEV_PR_ARG, __entry->skb)
);
TRACE_EVENT(mt_tx_status_cleaned,
    TP_PROTO(struct mt7601u_dev *dev, int cleaned),
    TP_ARGS(dev, cleaned),
    TP_STRUCT__entry(
        DEV_ENTRY
        __field(int, cleaned)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        __entry->cleaned = cleaned;
    ),
    TP_printk(DEV_PR_FMT "%d", DEV_PR_ARG, __entry->cleaned)
);
TRACE_EVENT(mt_tx_status,
    TP_PROTO(struct mt7601u_dev *dev, u32 stat1, u32 stat2),
    TP_ARGS(dev, stat1, stat2),
    TP_STRUCT__entry(
        DEV_ENTRY
        __field(u32, stat1)    __field(u32, stat2)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        __entry->stat1 = stat1;
        __entry->stat2 = stat2;
    ),
    TP_printk(DEV_PR_FMT "%08x %08x",
          DEV_PR_ARG, __entry->stat1, __entry->stat2)
);
TRACE_EVENT(mt_rx_dma_aggr,
    TP_PROTO(struct mt7601u_dev *dev, int cnt, bool paged),
    TP_ARGS(dev, cnt, paged),
    TP_STRUCT__entry(
        DEV_ENTRY
        __field(u8, cnt)
        __field(bool, paged)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        __entry->cnt = cnt;
        __entry->paged = paged;
    ),
    TP_printk(DEV_PR_FMT "cnt:%d paged:%d",
          DEV_PR_ARG, __entry->cnt, __entry->paged)
);
DEFINE_EVENT(dev_simple_evt, set_key,
    TP_PROTO(struct mt7601u_dev *dev, u8 val),
    TP_ARGS(dev, val)
);
TRACE_EVENT(set_shared_key,
    TP_PROTO(struct mt7601u_dev *dev, u8 vid, u8 key),
    TP_ARGS(dev, vid, key),
    TP_STRUCT__entry(
        DEV_ENTRY
        __field(u8, vid)
        __field(u8, key)
    ),
    TP_fast_assign(
        DEV_ASSIGN;
        __entry->vid = vid;
        __entry->key = key;
    ),
    TP_printk(DEV_PR_FMT "phy:%02hhx off:%02hhx",
          DEV_PR_ARG, __entry->vid, __entry->key)
);
#endif
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE trace
#include <trace/define_trace.h>
linux-bsp/drivers/mt7601u-sta/tx.c
New file
@@ -0,0 +1,322 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#include "mt7601u.h"
#include "trace.h"
enum mt76_txq_id {
    MT_TXQ_VO = IEEE80211_AC_VO,
    MT_TXQ_VI = IEEE80211_AC_VI,
    MT_TXQ_BE = IEEE80211_AC_BE,
    MT_TXQ_BK = IEEE80211_AC_BK,
    MT_TXQ_PSD,
    MT_TXQ_MCU,
    __MT_TXQ_MAX
};
/* Hardware uses mirrored order of queues with Q0 having the highest priority */
static u8 q2hwq(u8 q)
{
    return q ^ 0x3;
}
/* Take mac80211 Q id from the skb and translate it to hardware Q id */
static u8 skb2q(struct sk_buff *skb)
{
    int qid = skb_get_queue_mapping(skb);
    if (WARN_ON(qid >= MT_TXQ_PSD)) {
        qid = MT_TXQ_BE;
        skb_set_queue_mapping(skb, qid);
    }
    return q2hwq(qid);
}
/* Note: TX retry reporting is a bit broken.
 *     Retries are reported only once per AMPDU and often come a frame early
 *     i.e. they are reported in the last status preceding the AMPDU. Apart
 *     from the fact that it's hard to know the length of the AMPDU (which is
 *     required to know to how many consecutive frames retries should be
 *     applied), if status comes early on full FIFO it gets lost and retries
 *     of the whole AMPDU become invisible.
 *     As a work-around encode the desired rate in PKT_ID of TX descriptor
 *     and based on that guess the retries (every rate is tried once).
 *     Only downside here is that for MCS0 we have to rely solely on
 *     transmission failures as no retries can ever be reported.
 *     Not having to read EXT_FIFO has a nice effect of doubling the number
 *     of reports which can be fetched.
 *     Also the vendor driver never uses the EXT_FIFO register so it may be
 *     undertested.
 */
static u8 mt7601u_tx_pktid_enc(struct mt7601u_dev *dev, u8 rate, bool is_probe)
{
    u8 encoded = (rate + 1) + is_probe *  8;
    /* Because PKT_ID 0 disables status reporting only 15 values are
     * available but 16 are needed (8 MCS * 2 for encoding is_probe)
     * - we need to cram together two rates. MCS0 and MCS7 with is_probe
     * share PKT_ID 9.
     */
    if (is_probe && rate == 7)
        return encoded - 7;
    return encoded;
}
static void
mt7601u_tx_pktid_dec(struct mt7601u_dev *dev, struct mt76_tx_status *stat)
{
    u8 req_rate = stat->pktid;
    u8 eff_rate = stat->rate & 0x7;
    req_rate -= 1;
    if (req_rate > 7) {
        stat->is_probe = true;
        req_rate -= 8;
        /* Decide between MCS0 and MCS7 which share pktid 9 */
        if (!req_rate && eff_rate)
            req_rate = 7;
    }
    stat->retry = req_rate - eff_rate;
}
static void mt7601u_tx_skb_remove_dma_overhead(struct sk_buff *skb,
                           struct ieee80211_tx_info *info)
{
    int pkt_len = (unsigned long)info->status.status_driver_data[0];
    skb_pull(skb, sizeof(struct mt76_txwi) + 4);
    if (ieee80211_get_hdrlen_from_skb(skb) % 4)
        mt76_remove_hdr_pad(skb);
    skb_trim(skb, pkt_len);
}
void mt7601u_tx_status(struct mt7601u_dev *dev, struct sk_buff *skb)
{
    struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
    mt7601u_tx_skb_remove_dma_overhead(skb, info);
    ieee80211_tx_info_clear_status(info);
    info->status.rates[0].idx = -1;
    info->flags |= IEEE80211_TX_STAT_ACK;
    spin_lock(&dev->mac_lock);
    ieee80211_tx_status(dev->hw, skb);
    spin_unlock(&dev->mac_lock);
}
static int mt7601u_skb_rooms(struct mt7601u_dev *dev, struct sk_buff *skb)
{
    int hdr_len = ieee80211_get_hdrlen_from_skb(skb);
    u32 need_head;
    need_head = sizeof(struct mt76_txwi) + 4;
    if (hdr_len % 4)
        need_head += 2;
    return skb_cow(skb, need_head);
}
static struct mt76_txwi *
mt7601u_push_txwi(struct mt7601u_dev *dev, struct sk_buff *skb,
          struct ieee80211_sta *sta, struct mt76_wcid *wcid,
          int pkt_len)
{
    struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
    struct ieee80211_tx_rate *rate = &info->control.rates[0];
    struct mt76_txwi *txwi;
    unsigned long flags;
    bool is_probe;
    u32 pkt_id;
    u16 rate_ctl;
    u8 nss;
    txwi = (struct mt76_txwi *)skb_push(skb, sizeof(struct mt76_txwi));
    memset(txwi, 0, sizeof(*txwi));
    if (!wcid->tx_rate_set)
        ieee80211_get_tx_rates(info->control.vif, sta, skb,
                       info->control.rates, 1);
    spin_lock_irqsave(&dev->lock, flags);
    if (rate->idx < 0 || !rate->count)
        rate_ctl = wcid->tx_rate;
    else
        rate_ctl = mt76_mac_tx_rate_val(dev, rate, &nss);
    spin_unlock_irqrestore(&dev->lock, flags);
    txwi->rate_ctl = cpu_to_le16(rate_ctl);
    if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
        txwi->ack_ctl |= MT_TXWI_ACK_CTL_REQ;
    if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
        txwi->ack_ctl |= MT_TXWI_ACK_CTL_NSEQ;
    if ((info->flags & IEEE80211_TX_CTL_AMPDU) && sta) {
        u8 ba_size = IEEE80211_MIN_AMPDU_BUF;
        ba_size <<= sta->ht_cap.ampdu_factor;
        ba_size = min_t(int, 63, ba_size);
        if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
            ba_size = 0;
        txwi->ack_ctl |= MT76_SET(MT_TXWI_ACK_CTL_BA_WINDOW, ba_size);
        txwi->flags = cpu_to_le16(MT_TXWI_FLAGS_AMPDU |
                      MT76_SET(MT_TXWI_FLAGS_MPDU_DENSITY,
                           sta->ht_cap.ampdu_density));
        if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
            txwi->flags = 0;
    }
    txwi->wcid = wcid->idx;
    is_probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
    pkt_id = mt7601u_tx_pktid_enc(dev, rate_ctl & 0x7, is_probe);
    pkt_len |= MT76_SET(MT_TXWI_LEN_PKTID, pkt_id);
    txwi->len_ctl = cpu_to_le16(pkt_len);
    return txwi;
}
void mt7601u_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
        struct sk_buff *skb)
{
    struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
    struct mt7601u_dev *dev = hw->priv;
    struct ieee80211_vif *vif = info->control.vif;
    struct ieee80211_sta *sta = control->sta;
    struct mt76_sta *msta = NULL;
    struct mt76_wcid *wcid = dev->mon_wcid;
    struct mt76_txwi *txwi;
    int pkt_len = skb->len;
    int hw_q = skb2q(skb);
    BUILD_BUG_ON(ARRAY_SIZE(info->status.status_driver_data) < 1);
    info->status.status_driver_data[0] = (void *)(unsigned long)pkt_len;
    if (mt7601u_skb_rooms(dev, skb) || mt76_insert_hdr_pad(skb)) {
        ieee80211_free_txskb(dev->hw, skb);
        return;
    }
    if (sta) {
        msta = (struct mt76_sta *) sta->drv_priv;
        wcid = &msta->wcid;
    } else if (vif) {
        struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
        wcid = &mvif->group_wcid;
    }
    txwi = mt7601u_push_txwi(dev, skb, sta, wcid, pkt_len);
    if (mt7601u_dma_enqueue_tx(dev, skb, wcid, hw_q))
        return;
    trace_mt_tx(dev, skb, msta, txwi);
}
void mt7601u_tx_stat(struct work_struct *work)
{
    struct mt7601u_dev *dev = container_of(work, struct mt7601u_dev,
                           stat_work.work);
    struct mt76_tx_status stat;
    unsigned long flags;
    int cleaned = 0;
    while (!test_bit(MT7601U_STATE_REMOVED, &dev->state)) {
        stat = mt7601u_mac_fetch_tx_status(dev);
        if (!stat.valid)
            break;
        mt7601u_tx_pktid_dec(dev, &stat);
        mt76_send_tx_status(dev, &stat);
        cleaned++;
    }
    trace_mt_tx_status_cleaned(dev, cleaned);
    spin_lock_irqsave(&dev->tx_lock, flags);
    if (cleaned)
        queue_delayed_work(dev->stat_wq, &dev->stat_work,
                   msecs_to_jiffies(10));
    else if (test_and_clear_bit(MT7601U_STATE_MORE_STATS, &dev->state))
        queue_delayed_work(dev->stat_wq, &dev->stat_work,
                   msecs_to_jiffies(20));
    else
        clear_bit(MT7601U_STATE_READING_STATS, &dev->state);
    spin_unlock_irqrestore(&dev->tx_lock, flags);
}
int mt7601u_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
            u16 queue, const struct ieee80211_tx_queue_params *params)
{
    struct mt7601u_dev *dev = hw->priv;
    u8 cw_min = 5, cw_max = 10, hw_q = q2hwq(queue);
    u32 val;
    /* TODO: should we do funny things with the parameters?
     *     See what mt7601u_set_default_edca() used to do in init.c.
     */
    if (params->cw_min)
        cw_min = fls(params->cw_min);
    if (params->cw_max)
        cw_max = fls(params->cw_max);
    WARN_ON(params->txop > 0xff);
    WARN_ON(params->aifs > 0xf);
    WARN_ON(cw_min > 0xf);
    WARN_ON(cw_max > 0xf);
    val = MT76_SET(MT_EDCA_CFG_AIFSN, params->aifs) |
          MT76_SET(MT_EDCA_CFG_CWMIN, cw_min) |
          MT76_SET(MT_EDCA_CFG_CWMAX, cw_max);
    /* TODO: based on user-controlled EnableTxBurst var vendor drv sets
     *     a really long txop on AC0 (see connect.c:2009) but only on
     *     connect? When not connected should be 0.
     */
    if (!hw_q)
        val |= 0x60;
    else
        val |= MT76_SET(MT_EDCA_CFG_TXOP, params->txop);
    mt76_wr(dev, MT_EDCA_CFG_AC(hw_q), val);
    val = mt76_rr(dev, MT_WMM_TXOP(hw_q));
    val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(hw_q));
    val |= params->txop << MT_WMM_TXOP_SHIFT(hw_q);
    mt76_wr(dev, MT_WMM_TXOP(hw_q), val);
    val = mt76_rr(dev, MT_WMM_AIFSN);
    val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(hw_q));
    val |= params->aifs << MT_WMM_AIFSN_SHIFT(hw_q);
    mt76_wr(dev, MT_WMM_AIFSN, val);
    val = mt76_rr(dev, MT_WMM_CWMIN);
    val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(hw_q));
    val |= cw_min << MT_WMM_CWMIN_SHIFT(hw_q);
    mt76_wr(dev, MT_WMM_CWMIN, val);
    val = mt76_rr(dev, MT_WMM_CWMAX);
    val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(hw_q));
    val |= cw_max << MT_WMM_CWMAX_SHIFT(hw_q);
    mt76_wr(dev, MT_WMM_CWMAX, val);
    return 0;
}
linux-bsp/drivers/mt7601u-sta/usb.c
New file
@@ -0,0 +1,362 @@
/*
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>
#include "mt7601u.h"
#include "usb.h"
#include "trace.h"
static struct usb_device_id mt7601u_device_table[] = {
    { USB_DEVICE(0x0b05, 0x17d3) },
    { USB_DEVICE(0x0e8d, 0x760a) },
    { USB_DEVICE(0x0e8d, 0x760b) },
    { USB_DEVICE(0x13d3, 0x3431) },
    { USB_DEVICE(0x13d3, 0x3434) },
    { USB_DEVICE(0x148f, 0x7601) },
    { USB_DEVICE(0x148f, 0x760a) },
    { USB_DEVICE(0x148f, 0x760b) },
    { USB_DEVICE(0x148f, 0x760c) },
    { USB_DEVICE(0x148f, 0x760d) },
    { USB_DEVICE(0x2001, 0x3d04) },
    { USB_DEVICE(0x2717, 0x4106) },
    { USB_DEVICE(0x2955, 0x0001) },
    { USB_DEVICE(0x2955, 0x1001) },
    { USB_DEVICE(0x2a5f, 0x1000) },
    { USB_DEVICE(0x7392, 0x7710) },
    { 0, }
};
bool mt7601u_usb_alloc_buf(struct mt7601u_dev *dev, size_t len,
               struct mt7601u_dma_buf *buf)
{
    struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
    buf->len = len;
    buf->urb = usb_alloc_urb(0, GFP_KERNEL);
    buf->buf = usb_alloc_coherent(usb_dev, buf->len, GFP_KERNEL, &buf->dma);
    return !buf->urb || !buf->buf;
}
void mt7601u_usb_free_buf(struct mt7601u_dev *dev, struct mt7601u_dma_buf *buf)
{
    struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
    usb_free_coherent(usb_dev, buf->len, buf->buf, buf->dma);
    usb_free_urb(buf->urb);
}
int mt7601u_usb_submit_buf(struct mt7601u_dev *dev, int dir, int ep_idx,
               struct mt7601u_dma_buf *buf, gfp_t gfp,
               usb_complete_t complete_fn, void *context)
{
    struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
    unsigned pipe;
    int ret;
    if (dir == USB_DIR_IN)
        pipe = usb_rcvbulkpipe(usb_dev, dev->in_eps[ep_idx]);
    else
        pipe = usb_sndbulkpipe(usb_dev, dev->out_eps[ep_idx]);
    usb_fill_bulk_urb(buf->urb, usb_dev, pipe, buf->buf, buf->len,
              complete_fn, context);
    buf->urb->transfer_dma = buf->dma;
    buf->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
    trace_mt_submit_urb(dev, buf->urb);
    ret = usb_submit_urb(buf->urb, gfp);
    if (ret)
        dev_err(dev->dev, "Error: submit URB dir:%d ep:%d failed:%d\n",
            dir, ep_idx, ret);
    return ret;
}
void mt7601u_complete_urb(struct urb *urb)
{
    struct completion *cmpl = urb->context;
    complete(cmpl);
}
int mt7601u_vendor_request(struct mt7601u_dev *dev, const u8 req,
               const u8 direction, const u16 val, const u16 offset,
               void *buf, const size_t buflen)
{
    int i, ret;
    struct usb_device *usb_dev = mt7601u_to_usb_dev(dev);
    const u8 req_type = direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
    const unsigned int pipe = (direction == USB_DIR_IN) ?
        usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
    for (i = 0; i < MT_VEND_REQ_MAX_RETRY; i++) {
        ret = usb_control_msg(usb_dev, pipe, req, req_type,
                      val, offset, buf, buflen,
                      MT_VEND_REQ_TOUT_MS);
        trace_mt_vend_req(dev, pipe, req, req_type, val, offset,
                  buf, buflen, ret);
        if (ret == -ENODEV)
            set_bit(MT7601U_STATE_REMOVED, &dev->state);
        if (ret >= 0 || ret == -ENODEV)
            return ret;
        msleep(5);
    }
    dev_err(dev->dev, "Vendor request req:%02x off:%04x failed:%d\n",
        req, offset, ret);
    return ret;
}
void mt7601u_vendor_reset(struct mt7601u_dev *dev)
{
    mt7601u_vendor_request(dev, MT_VEND_DEV_MODE, USB_DIR_OUT,
                   MT_VEND_DEV_MODE_RESET, 0, NULL, 0);
}
u32 mt7601u_rr(struct mt7601u_dev *dev, u32 offset)
{
    int ret;
    u32 val = ~0;
    WARN_ONCE(offset > USHRT_MAX, "read high off:%08x", offset);
    mutex_lock(&dev->vendor_req_mutex);
    ret = mt7601u_vendor_request(dev, MT_VEND_MULTI_READ, USB_DIR_IN,
                     0, offset, dev->vend_buf, MT_VEND_BUF);
    if (ret == MT_VEND_BUF)
        val = get_unaligned_le32(dev->vend_buf);
    else if (ret > 0)
        dev_err(dev->dev, "Error: wrong size read:%d off:%08x\n",
            ret, offset);
    mutex_unlock(&dev->vendor_req_mutex);
    trace_reg_read(dev, offset, val);
    return val;
}
int mt7601u_vendor_single_wr(struct mt7601u_dev *dev, const u8 req,
                 const u16 offset, const u32 val)
{
    int ret;
    mutex_lock(&dev->vendor_req_mutex);
    ret = mt7601u_vendor_request(dev, req, USB_DIR_OUT,
                     val & 0xffff, offset, NULL, 0);
    if (!ret)
        ret = mt7601u_vendor_request(dev, req, USB_DIR_OUT,
                         val >> 16, offset + 2, NULL, 0);
    mutex_unlock(&dev->vendor_req_mutex);
    return ret;
}
void mt7601u_wr(struct mt7601u_dev *dev, u32 offset, u32 val)
{
    WARN_ONCE(offset > USHRT_MAX, "write high off:%08x", offset);
    mt7601u_vendor_single_wr(dev, MT_VEND_WRITE, offset, val);
    trace_reg_write(dev, offset, val);
}
u32 mt7601u_rmw(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val)
{
    val |= mt7601u_rr(dev, offset) & ~mask;
    mt7601u_wr(dev, offset, val);
    return val;
}
u32 mt7601u_rmc(struct mt7601u_dev *dev, u32 offset, u32 mask, u32 val)
{
    u32 reg = mt7601u_rr(dev, offset);
    val |= reg & ~mask;
    if (reg != val)
        mt7601u_wr(dev, offset, val);
    return val;
}
void mt7601u_wr_copy(struct mt7601u_dev *dev, u32 offset,
             const void *data, int len)
{
    WARN_ONCE(offset & 3, "unaligned write copy off:%08x", offset);
    WARN_ONCE(len & 3, "short write copy off:%08x", offset);
    mt7601u_burst_write_regs(dev, offset, data, len / 4);
}
void mt7601u_addr_wr(struct mt7601u_dev *dev, const u32 offset, const u8 *addr)
{
    mt7601u_wr(dev, offset, get_unaligned_le32(addr));
    mt7601u_wr(dev, offset + 4, addr[4] | addr[5] << 8);
}
static int mt7601u_assign_pipes(struct usb_interface *usb_intf,
                struct mt7601u_dev *dev)
{
    struct usb_endpoint_descriptor *ep_desc;
    struct usb_host_interface *intf_desc = usb_intf->cur_altsetting;
    unsigned i, ep_i = 0, ep_o = 0;
    BUILD_BUG_ON(sizeof(dev->in_eps) < __MT_EP_IN_MAX);
    BUILD_BUG_ON(sizeof(dev->out_eps) < __MT_EP_OUT_MAX);
    for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
        ep_desc = &intf_desc->endpoint[i].desc;
        if (usb_endpoint_is_bulk_in(ep_desc) &&
            ep_i++ < __MT_EP_IN_MAX) {
            dev->in_eps[ep_i - 1] = usb_endpoint_num(ep_desc);
            dev->in_max_packet = usb_endpoint_maxp(ep_desc);
            /* Note: this is ignored by usb sub-system but vendor
             *     code does it. We can drop this at some point.
             */
            dev->in_eps[ep_i - 1] |= USB_DIR_IN;
        } else if (usb_endpoint_is_bulk_out(ep_desc) &&
               ep_o++ < __MT_EP_OUT_MAX) {
            dev->out_eps[ep_o - 1] = usb_endpoint_num(ep_desc);
            dev->out_max_packet = usb_endpoint_maxp(ep_desc);
        }
    }
    if (ep_i != __MT_EP_IN_MAX || ep_o != __MT_EP_OUT_MAX) {
        dev_err(dev->dev, "Error: wrong pipe number in:%d out:%d\n",
            ep_i, ep_o);
        return -EINVAL;
    }
    return 0;
}
static int mt7601u_probe(struct usb_interface *usb_intf,
             const struct usb_device_id *id)
{
    struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
    struct mt7601u_dev *dev;
    u32 asic_rev, mac_rev;
    int ret;
    dev = mt7601u_alloc_device(&usb_intf->dev);
    if (!dev)
        return -ENOMEM;
    usb_dev = usb_get_dev(usb_dev);
    usb_reset_device(usb_dev);
    usb_set_intfdata(usb_intf, dev);
    dev->vend_buf = devm_kmalloc(dev->dev, MT_VEND_BUF, GFP_KERNEL);
    if (!dev->vend_buf) {
        ret = -ENOMEM;
        goto err;
    }
    ret = mt7601u_assign_pipes(usb_intf, dev);
    if (ret)
        goto err;
    ret = mt7601u_wait_asic_ready(dev);
    if (ret)
        goto err;
    asic_rev = mt7601u_rr(dev, MT_ASIC_VERSION);
    mac_rev = mt7601u_rr(dev, MT_MAC_CSR0);
    dev_info(dev->dev, "ASIC revision: %08x MAC revision: %08x\n",
         asic_rev, mac_rev);
    /* Note: vendor driver skips this check for MT7601U */
    if (!(mt7601u_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL))
        dev_warn(dev->dev, "Warning: eFUSE not present\n");
    ret = mt7601u_init_hardware(dev);
    if (ret)
        goto err;
    ret = mt7601u_register_device(dev);
    if (ret)
        goto err_hw;
    set_bit(MT7601U_STATE_INITIALIZED, &dev->state);
    return 0;
err_hw:
    mt7601u_cleanup(dev);
err:
    usb_set_intfdata(usb_intf, NULL);
    usb_put_dev(interface_to_usbdev(usb_intf));
    destroy_workqueue(dev->stat_wq);
    ieee80211_free_hw(dev->hw);
    return ret;
}
static void mt7601u_disconnect(struct usb_interface *usb_intf)
{
    struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
    ieee80211_unregister_hw(dev->hw);
    mt7601u_cleanup(dev);
    usb_set_intfdata(usb_intf, NULL);
    usb_put_dev(interface_to_usbdev(usb_intf));
    destroy_workqueue(dev->stat_wq);
    ieee80211_free_hw(dev->hw);
}
static int mt7601u_suspend(struct usb_interface *usb_intf, pm_message_t state)
{
    struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
    mt7601u_cleanup(dev);
    return 0;
}
static int mt7601u_resume(struct usb_interface *usb_intf)
{
    struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
    int ret;
    ret = mt7601u_init_hardware(dev);
    if (ret)
        return ret;
    set_bit(MT7601U_STATE_INITIALIZED, &dev->state);
    return 0;
}
MODULE_DEVICE_TABLE(usb, mt7601u_device_table);
MODULE_FIRMWARE(MT7601U_FIRMWARE);
MODULE_LICENSE("GPL");
static struct usb_driver mt7601u_driver = {
    .name        = KBUILD_MODNAME,
    .id_table    = mt7601u_device_table,
    .probe        = mt7601u_probe,
    .disconnect    = mt7601u_disconnect,
    .suspend    = mt7601u_suspend,
    .resume        = mt7601u_resume,
    .reset_resume    = mt7601u_resume,
    .soft_unbind    = 1,
    .disable_hub_initiated_lpm = 1,
};
module_usb_driver(mt7601u_driver);
linux-bsp/drivers/mt7601u-sta/usb.h
New file
@@ -0,0 +1,79 @@
/*
 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#ifndef __MT7601U_USB_H
#define __MT7601U_USB_H
#include "mt7601u.h"
#define MT7601U_FIRMWARE    "mt7601u.bin"
#define MT_VEND_REQ_MAX_RETRY    10
#define MT_VEND_REQ_TOUT_MS    300
#define MT_VEND_DEV_MODE_RESET    1
#define MT_VEND_BUF        sizeof(__le32)
enum mt_vendor_req {
    MT_VEND_DEV_MODE = 1,
    MT_VEND_WRITE = 2,
    MT_VEND_MULTI_READ = 7,
    MT_VEND_WRITE_FCE = 0x42,
};
enum mt_usb_ep_in {
    MT_EP_IN_PKT_RX,
    MT_EP_IN_CMD_RESP,
    __MT_EP_IN_MAX,
};
enum mt_usb_ep_out {
    MT_EP_OUT_INBAND_CMD,
    MT_EP_OUT_AC_BK,
    MT_EP_OUT_AC_BE,
    MT_EP_OUT_AC_VI,
    MT_EP_OUT_AC_VO,
    MT_EP_OUT_HCCA,
    __MT_EP_OUT_MAX,
};
static inline struct usb_device *mt7601u_to_usb_dev(struct mt7601u_dev *mt7601u)
{
    return interface_to_usbdev(to_usb_interface(mt7601u->dev));
}
static inline bool mt7601u_urb_has_error(struct urb *urb)
{
    return urb->status &&
        urb->status != -ENOENT &&
        urb->status != -ECONNRESET &&
        urb->status != -ESHUTDOWN;
}
bool mt7601u_usb_alloc_buf(struct mt7601u_dev *dev, size_t len,
               struct mt7601u_dma_buf *buf);
void mt7601u_usb_free_buf(struct mt7601u_dev *dev, struct mt7601u_dma_buf *buf);
int mt7601u_usb_submit_buf(struct mt7601u_dev *dev, int dir, int ep_idx,
               struct mt7601u_dma_buf *buf, gfp_t gfp,
               usb_complete_t complete_fn, void *context);
void mt7601u_complete_urb(struct urb *urb);
int mt7601u_vendor_request(struct mt7601u_dev *dev, const u8 req,
               const u8 direction, const u16 val, const u16 offset,
               void *buf, const size_t buflen);
void mt7601u_vendor_reset(struct mt7601u_dev *dev);
int mt7601u_vendor_single_wr(struct mt7601u_dev *dev, const u8 req,
                 const u16 offset, const u32 val);
#endif
linux-bsp/drivers/mt7601u-sta/util.c
New file
@@ -0,0 +1,42 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#include "mt7601u.h"
void mt76_remove_hdr_pad(struct sk_buff *skb)
{
    int len = ieee80211_get_hdrlen_from_skb(skb);
    memmove(skb->data + 2, skb->data, len);
    skb_pull(skb, 2);
}
int mt76_insert_hdr_pad(struct sk_buff *skb)
{
    int len = ieee80211_get_hdrlen_from_skb(skb);
    int ret;
    if (len % 4 == 0)
        return 0;
    ret = skb_cow(skb, 2);
    if (ret)
        return ret;
    skb_push(skb, 2);
    memmove(skb->data, skb->data + 2, len);
    skb->data[len] = 0;
    skb->data[len + 1] = 0;
    return 0;
}
linux-bsp/drivers/mt7601u-sta/util.h
New file
@@ -0,0 +1,77 @@
/*
 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
 * Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation
 *
 * 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.
 */
#ifndef __MT76_UTIL_H
#define __MT76_UTIL_H
/*
 * Power of two check, this will check
 * if the mask that has been given contains and contiguous set of bits.
 * Note that we cannot use the is_power_of_2() function since this
 * check must be done at compile-time.
 */
#define is_power_of_two(x)    ( !((x) & ((x)-1)) )
#define low_bit_mask(x)        ( ((x)-1) & ~(x) )
#define is_valid_mask(x)    is_power_of_two(1LU + (x) + low_bit_mask(x))
/*
 * Macros to find first set bit in a variable.
 * These macros behave the same as the __ffs() functions but
 * the most important difference that this is done during
 * compile-time rather then run-time.
 */
#define compile_ffs2(__x) \
    __builtin_choose_expr(((__x) & 0x1), 0, 1)
#define compile_ffs4(__x) \
    __builtin_choose_expr(((__x) & 0x3), \
                  (compile_ffs2((__x))), \
                  (compile_ffs2((__x) >> 2) + 2))
#define compile_ffs8(__x) \
    __builtin_choose_expr(((__x) & 0xf), \
                  (compile_ffs4((__x))), \
                  (compile_ffs4((__x) >> 4) + 4))
#define compile_ffs16(__x) \
    __builtin_choose_expr(((__x) & 0xff), \
                  (compile_ffs8((__x))), \
                  (compile_ffs8((__x) >> 8) + 8))
#define compile_ffs32(__x) \
    __builtin_choose_expr(((__x) & 0xffff), \
                  (compile_ffs16((__x))), \
                  (compile_ffs16((__x) >> 16) + 16))
/*
 * This macro will check the requirements for the FIELD{8,16,32} macros
 * The mask should be a constant non-zero contiguous set of bits which
 * does not exceed the given typelimit.
 */
#define FIELD_CHECK(__mask) \
    BUILD_BUG_ON(!(__mask) || !is_valid_mask(__mask))
#define MT76_SET(_mask, _val)                        \
    ({                                \
        FIELD_CHECK(_mask);                    \
        (((u32) (_val)) << compile_ffs32(_mask)) & _mask;    \
    })
#define MT76_GET(_mask, _val)                        \
    ({                                \
        FIELD_CHECK(_mask);                    \
        (u32) (((_val) & _mask) >> compile_ffs32(_mask));    \
    })
#endif
linux-bsp/drivers/rtl8188eus/Kconfig
New file
@@ -0,0 +1,6 @@
config RTL8188EU
    tristate "Realtek 8188E USB WiFi"
    depends on USB
    ---help---
      Help message of RTL8188EU
linux-bsp/drivers/rtl8188eus/LICENSE
New file
@@ -0,0 +1,12 @@
SOUI License
The MIT License (MIT)
Copyright (c) 2016 Ã†Ã´Â³ÃŒÃˆÃ­Â¼Ã¾
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
linux-bsp/drivers/rtl8188eus/Makefile
New file
@@ -0,0 +1,1957 @@
EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS)
EXTRA_CFLAGS += -O2
#EXTRA_CFLAGS += -O3
#EXTRA_CFLAGS += -Wall
#EXTRA_CFLAGS += -Wextra
#EXTRA_CFLAGS += -Werror
#EXTRA_CFLAGS += -pedantic
#EXTRA_CFLAGS += -Wshadow -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes
EXTRA_CFLAGS += -Wno-unused-variable
EXTRA_CFLAGS += -Wno-unused-value
EXTRA_CFLAGS += -Wno-unused-label
EXTRA_CFLAGS += -Wno-unused-parameter
EXTRA_CFLAGS += -Wno-unused-function
EXTRA_CFLAGS += -Wno-unused
#EXTRA_CFLAGS += -Wno-uninitialized
GCC_VER_49 := $(shell echo `$(CC) -dumpversion | cut -f1-2 -d.` \>= 4.9 | bc )
ifeq ($(GCC_VER_49),1)
EXTRA_CFLAGS += -Wno-date-time    # Fix compile error && warning on gcc 4.9 and later
endif
EXTRA_CFLAGS += -I$(src)/include
EXTRA_CFLAGS += -I$(src)/hal/phydm
EXTRA_LDFLAGS += --strip-debug
CONFIG_AUTOCFG_CP = n
########################## WIFI IC ############################
CONFIG_MULTIDRV = n
CONFIG_RTL8188E = y
CONFIG_RTL8812A = n
CONFIG_RTL8821A = n
CONFIG_RTL8192E = n
CONFIG_RTL8723B = n
CONFIG_RTL8814A = n
CONFIG_RTL8723C = n
CONFIG_RTL8188F = n
CONFIG_RTL8822B = n
CONFIG_RTL8723D = n
CONFIG_RTL8821C = n
######################### Interface ###########################
CONFIG_USB_HCI = y
CONFIG_PCI_HCI = n
CONFIG_SDIO_HCI = n
CONFIG_GSPI_HCI = n
########################## Features ###########################
CONFIG_MP_INCLUDED = y
CONFIG_POWER_SAVING = y
CONFIG_USB_AUTOSUSPEND = n
CONFIG_HW_PWRP_DETECTION = n
CONFIG_WIFI_TEST = n
CONFIG_BT_COEXIST = n
CONFIG_INTEL_WIDI = n
CONFIG_WAPI_SUPPORT = n
CONFIG_EFUSE_CONFIG_FILE = y
CONFIG_EXT_CLK = n
CONFIG_TRAFFIC_PROTECT = y
CONFIG_LOAD_PHY_PARA_FROM_FILE = y
CONFIG_TXPWR_BY_RATE_EN = n
CONFIG_TXPWR_LIMIT_EN = n
CONFIG_RTW_ADAPTIVITY_EN = disable
CONFIG_RTW_ADAPTIVITY_MODE = normal
CONFIG_SIGNAL_SCALE_MAPPING = n
CONFIG_80211W = n
CONFIG_REDUCE_TX_CPU_LOADING = n
CONFIG_BR_EXT = y
CONFIG_TDLS = n
CONFIG_WIFI_MONITOR = y
CONFIG_MCC_MODE = n
CONFIG_APPEND_VENDOR_IE_ENABLE = n
CONFIG_RTW_NAPI = y
CONFIG_RTW_GRO = y
########################## Debug ###########################
CONFIG_RTW_DEBUG = n
# default log level is _DRV_INFO_ = 4,
# please refer to "How_to_set_driver_debug_log_level.doc" to set the available level.
CONFIG_RTW_LOG_LEVEL = 4
######################## Wake On Lan ##########################
CONFIG_WOWLAN = n
CONFIG_GPIO_WAKEUP = n
CONFIG_DEFAULT_PATTERNS_EN = n
CONFIG_WAKEUP_GPIO_IDX = default
CONFIG_HIGH_ACTIVE = n
CONFIG_PNO_SUPPORT = n
CONFIG_PNO_SET_DEBUG = n
CONFIG_AP_WOWLAN = n
######### Notify SDIO Host Keep Power During Syspend ##########
CONFIG_RTW_SDIO_PM_KEEP_POWER = y
###################### MP HW TX MODE FOR VHT #######################
CONFIG_MP_VHT_HW_TX_MODE = n
###################### Platform Related #######################
CONFIG_PLATFORM_I386_PC = n
CONFIG_PLATFORM_ARM_SAMA5D4 = y
CONFIG_PLATFORM_BCM2709 = n
CONFIG_PLATFORM_ANDROID_X86 = n
CONFIG_PLATFORM_ANDROID_X86_N70 = n
CONFIG_PLATFORM_ANDROID_INTEL_X86 = n
CONFIG_PLATFORM_JB_X86 = n
CONFIG_PLATFORM_ARM_S3C2K4 = n
CONFIG_PLATFORM_ARM_PXA2XX = n
CONFIG_PLATFORM_ARM_S3C6K4 = n
CONFIG_PLATFORM_MIPS_RMI = n
CONFIG_PLATFORM_RTD2880B = n
CONFIG_PLATFORM_MIPS_AR9132 = n
CONFIG_PLATFORM_RTK_DMP = n
CONFIG_PLATFORM_MIPS_PLM = n
CONFIG_PLATFORM_MSTAR389 = n
CONFIG_PLATFORM_MT53XX = n
CONFIG_PLATFORM_ARM_MX51_241H = n
CONFIG_PLATFORM_FS_MX61 = n
CONFIG_PLATFORM_ACTIONS_ATJ227X = n
CONFIG_PLATFORM_TEGRA3_CARDHU = n
CONFIG_PLATFORM_TEGRA4_DALMORE = n
CONFIG_PLATFORM_ARM_TCC8900 = n
CONFIG_PLATFORM_ARM_TCC8920 = n
CONFIG_PLATFORM_ARM_TCC8920_JB42 = n
CONFIG_PLATFORM_ARM_TCC8930_JB42 = n
CONFIG_PLATFORM_ARM_RK2818 = n
CONFIG_PLATFORM_ARM_RK3066 = n
CONFIG_PLATFORM_ARM_RK3188 = n
CONFIG_PLATFORM_ARM_URBETTER = n
CONFIG_PLATFORM_ARM_TI_PANDA = n
CONFIG_PLATFORM_MIPS_JZ4760 = n
CONFIG_PLATFORM_DMP_PHILIPS = n
CONFIG_PLATFORM_MSTAR_TITANIA12 = n
CONFIG_PLATFORM_MSTAR = n
CONFIG_PLATFORM_SZEBOOK = n
CONFIG_PLATFORM_ARM_SUNxI = n
CONFIG_PLATFORM_ARM_SUN6I = n
CONFIG_PLATFORM_ARM_SUN7I = n
CONFIG_PLATFORM_ARM_SUN8I_W3P1 = n
CONFIG_PLATFORM_ARM_SUN8I_W5P1 = n
CONFIG_PLATFORM_ACTIONS_ATM702X = n
CONFIG_PLATFORM_ACTIONS_ATV5201 = n
CONFIG_PLATFORM_ACTIONS_ATM705X = n
CONFIG_PLATFORM_ARM_SUN50IW1P1 = n
CONFIG_PLATFORM_ARM_RTD299X = n
CONFIG_PLATFORM_ARM_SPREADTRUM_6820 = n
CONFIG_PLATFORM_ARM_SPREADTRUM_8810 = n
CONFIG_PLATFORM_ARM_WMT = n
CONFIG_PLATFORM_TI_DM365 = n
CONFIG_PLATFORM_MOZART = n
CONFIG_PLATFORM_RTK119X = n
CONFIG_PLATFORM_RTK129X = n
CONFIG_PLATFORM_NOVATEK_NT72668 = n
CONFIG_PLATFORM_HISILICON = n
CONFIG_PLATFORM_NV_TK1 = n
###############################################################
CONFIG_DRVEXT_MODULE = n
ifeq ($(CONFIG_PLATFORM_ANDROID_X86_N70), y)
export TopDIR := $(shell pwd)/../../../../../../kernel/drivers/net/wireless/rtl8188ee/
endif
export TopDIR ?= $(shell pwd)
########### COMMON  #################################
ifeq ($(CONFIG_GSPI_HCI), y)
HCI_NAME = gspi
endif
ifeq ($(CONFIG_SDIO_HCI), y)
HCI_NAME = sdio
endif
ifeq ($(CONFIG_USB_HCI), y)
HCI_NAME = usb
endif
ifeq ($(CONFIG_PCI_HCI), y)
HCI_NAME = pci
endif
_OS_INTFS_FILES :=    os_dep/osdep_service.o \
            os_dep/linux/os_intfs.o \
            os_dep/linux/$(HCI_NAME)_intf.o \
            os_dep/linux/$(HCI_NAME)_ops_linux.o \
            os_dep/linux/ioctl_linux.o \
            os_dep/linux/xmit_linux.o \
            os_dep/linux/mlme_linux.o \
            os_dep/linux/recv_linux.o \
            os_dep/linux/ioctl_cfg80211.o \
            os_dep/linux/rtw_cfgvendor.o \
            os_dep/linux/wifi_regd.o \
            os_dep/linux/rtw_android.o \
            os_dep/linux/rtw_proc.o
ifeq ($(CONFIG_MP_INCLUDED), y)
_OS_INTFS_FILES += os_dep/linux/ioctl_mp.o
endif
ifeq ($(CONFIG_SDIO_HCI), y)
_OS_INTFS_FILES += os_dep/linux/custom_gpio_linux.o
_OS_INTFS_FILES += os_dep/linux/$(HCI_NAME)_ops_linux.o
endif
ifeq ($(CONFIG_GSPI_HCI), y)
_OS_INTFS_FILES += os_dep/linux/custom_gpio_linux.o
_OS_INTFS_FILES += os_dep/linux/$(HCI_NAME)_ops_linux.o
endif
_HAL_INTFS_FILES :=    hal/hal_intf.o \
            hal/hal_com.o \
            hal/hal_com_phycfg.o \
            hal/hal_phy.o \
            hal/hal_dm.o \
            hal/hal_btcoex_wifionly.o \
            hal/hal_btcoex.o \
            hal/hal_mp.o \
            hal/hal_mcc.o \
            hal/hal_hci/hal_$(HCI_NAME).o \
            hal/led/hal_$(HCI_NAME)_led.o
_OUTSRC_FILES := hal/phydm/phydm_debug.o    \
        hal/phydm/phydm_antdiv.o\
        hal/phydm/phydm_antdect.o\
        hal/phydm/phydm_interface.o\
        hal/phydm/phydm_hwconfig.o\
        hal/phydm/phydm.o\
        hal/phydm/halphyrf_ce.o\
        hal/phydm/phydm_edcaturbocheck.o\
        hal/phydm/phydm_dig.o\
        hal/phydm/phydm_pathdiv.o\
        hal/phydm/phydm_rainfo.o\
        hal/phydm/phydm_dynamicbbpowersaving.o\
        hal/phydm/phydm_powertracking_ce.o\
        hal/phydm/phydm_dynamictxpower.o\
        hal/phydm/phydm_adaptivity.o\
        hal/phydm/phydm_cfotracking.o\
        hal/phydm/phydm_noisemonitor.o\
        hal/phydm/phydm_acs.o\
        hal/phydm/phydm_beamforming.o\
        hal/phydm/phydm_dfs.o\
        hal/phydm/txbf/halcomtxbf.o\
        hal/phydm/txbf/haltxbfinterface.o\
        hal/phydm/txbf/phydm_hal_txbf_api.o\
        hal/phydm/phydm_adc_sampling.o\
        hal/phydm/phydm_kfree.o\
        hal/phydm/phydm_ccx.o
EXTRA_CFLAGS += -I$(src)/platform
_PLATFORM_FILES := platform/platform_ops.o
EXTRA_CFLAGS += -I$(src)/hal/btc
_OUTSRC_FILES += hal/btc/halbtc8723bwifionly.o \
                hal/btc/halbtc8822bwifionly.o \
                hal/btc/halbtc8821cwifionly.o
ifeq ($(CONFIG_BT_COEXIST), y)
_OUTSRC_FILES += hal/btc/halbtc8192e1ant.o \
                hal/btc/halbtc8192e2ant.o \
                hal/btc/halbtc8723b1ant.o \
                hal/btc/halbtc8723b2ant.o \
                hal/btc/halbtc8812a1ant.o \
                hal/btc/halbtc8812a2ant.o \
                hal/btc/halbtc8821a1ant.o \
                hal/btc/halbtc8821a2ant.o \
                hal/btc/halbtc8703b1ant.o \
                hal/btc/halbtc8723d1ant.o \
                hal/btc/halbtc8723d2ant.o \
                hal/btc/halbtc8822b1ant.o \
                hal/btc/halbtc8822b2ant.o \
                hal/btc/halbtc8821c1ant.o \
                hal/btc/halbtc8821c2ant.o
endif
########### HAL_RTL8188E #################################
ifeq ($(CONFIG_RTL8188E), y)
RTL871X = rtl8188e
ifeq ($(CONFIG_SDIO_HCI), y)
MODULE_NAME = 8189es
endif
ifeq ($(CONFIG_GSPI_HCI), y)
MODULE_NAME = 8189es
endif
ifeq ($(CONFIG_USB_HCI), y)
MODULE_NAME = 8188eu
endif
ifeq ($(CONFIG_PCI_HCI), y)
MODULE_NAME = 8188ee
endif
EXTRA_CFLAGS += -DCONFIG_RTL8188E
_HAL_INTFS_FILES +=    hal/HalPwrSeqCmd.o \
                    hal/$(RTL871X)/Hal8188EPwrSeq.o\
                     hal/$(RTL871X)/$(RTL871X)_xmit.o\
                    hal/$(RTL871X)/$(RTL871X)_sreset.o
_HAL_INTFS_FILES +=    hal/$(RTL871X)/$(RTL871X)_hal_init.o \
            hal/$(RTL871X)/$(RTL871X)_phycfg.o \
            hal/$(RTL871X)/$(RTL871X)_rf6052.o \
            hal/$(RTL871X)/$(RTL871X)_dm.o \
            hal/$(RTL871X)/$(RTL871X)_rxdesc.o \
            hal/$(RTL871X)/$(RTL871X)_cmd.o \
            hal/$(RTL871X)/hal8188e_s_fw.o \
            hal/$(RTL871X)/hal8188e_t_fw.o \
            hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_halinit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_led.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_xmit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_recv.o
ifeq ($(CONFIG_SDIO_HCI), y)
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops.o
else
ifeq ($(CONFIG_GSPI_HCI), y)
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops.o
else
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops_linux.o
endif
endif
ifeq ($(CONFIG_USB_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8188E_USB.o
endif
ifeq ($(CONFIG_PCI_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8188E_PCIE.o
endif
ifeq ($(CONFIG_SDIO_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8188E_SDIO.o
endif
#hal/OUTSRC/$(RTL871X)/Hal8188EFWImg_CE.o
_OUTSRC_FILES += hal/phydm/$(RTL871X)/halhwimg8188e_mac.o\
        hal/phydm/$(RTL871X)/halhwimg8188e_bb.o\
        hal/phydm/$(RTL871X)/halhwimg8188e_rf.o\
        hal/phydm/$(RTL871X)/halphyrf_8188e_ce.o\
        hal/phydm/$(RTL871X)/phydm_regconfig8188e.o\
        hal/phydm/$(RTL871X)/hal8188erateadaptive.o\
        hal/phydm/$(RTL871X)/phydm_rtl8188e.o
endif
########### HAL_RTL8192E #################################
ifeq ($(CONFIG_RTL8192E), y)
RTL871X = rtl8192e
ifeq ($(CONFIG_SDIO_HCI), y)
MODULE_NAME = 8192es
endif
ifeq ($(CONFIG_USB_HCI), y)
MODULE_NAME = 8192eu
endif
ifeq ($(CONFIG_PCI_HCI), y)
MODULE_NAME = 8192ee
endif
EXTRA_CFLAGS += -DCONFIG_RTL8192E
_HAL_INTFS_FILES += hal/HalPwrSeqCmd.o \
                    hal/$(RTL871X)/Hal8192EPwrSeq.o\
                    hal/$(RTL871X)/$(RTL871X)_xmit.o\
                    hal/$(RTL871X)/$(RTL871X)_sreset.o
_HAL_INTFS_FILES +=    hal/$(RTL871X)/$(RTL871X)_hal_init.o \
            hal/$(RTL871X)/$(RTL871X)_phycfg.o \
            hal/$(RTL871X)/$(RTL871X)_rf6052.o \
            hal/$(RTL871X)/$(RTL871X)_dm.o \
            hal/$(RTL871X)/$(RTL871X)_rxdesc.o \
            hal/$(RTL871X)/$(RTL871X)_cmd.o \
            hal/$(RTL871X)/hal8192e_fw.o \
            hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_halinit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_led.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_xmit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_recv.o
ifeq ($(CONFIG_SDIO_HCI), y)
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops.o
else
ifeq ($(CONFIG_GSPI_HCI), y)
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops.o
else
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops_linux.o
endif
endif
ifeq ($(CONFIG_USB_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8192E_USB.o
endif
ifeq ($(CONFIG_PCI_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8192E_PCIE.o
endif
#hal/OUTSRC/$(RTL871X)/HalHWImg8188E_FW.o
_OUTSRC_FILES += hal/phydm/$(RTL871X)/halhwimg8192e_mac.o\
        hal/phydm/$(RTL871X)/halhwimg8192e_bb.o\
        hal/phydm/$(RTL871X)/halhwimg8192e_rf.o\
        hal/phydm/$(RTL871X)/halphyrf_8192e_ce.o\
        hal/phydm/$(RTL871X)/phydm_regconfig8192e.o\
        hal/phydm/$(RTL871X)/phydm_rtl8192e.o
endif
########### HAL_RTL8812A_RTL8821A #################################
ifneq ($(CONFIG_RTL8812A)_$(CONFIG_RTL8821A), n_n)
RTL871X = rtl8812a
ifeq ($(CONFIG_USB_HCI), y)
MODULE_NAME = 8812au
endif
ifeq ($(CONFIG_PCI_HCI), y)
MODULE_NAME = 8812ae
endif
ifeq ($(CONFIG_SDIO_HCI), y)
MODULE_NAME = 8812as
endif
_HAL_INTFS_FILES +=  hal/HalPwrSeqCmd.o \
                    hal/$(RTL871X)/Hal8812PwrSeq.o \
                    hal/$(RTL871X)/Hal8821APwrSeq.o\
                    hal/$(RTL871X)/$(RTL871X)_xmit.o\
                    hal/$(RTL871X)/$(RTL871X)_sreset.o
_HAL_INTFS_FILES +=    hal/$(RTL871X)/$(RTL871X)_hal_init.o \
            hal/$(RTL871X)/$(RTL871X)_phycfg.o \
            hal/$(RTL871X)/$(RTL871X)_rf6052.o \
            hal/$(RTL871X)/$(RTL871X)_dm.o \
            hal/$(RTL871X)/$(RTL871X)_rxdesc.o \
            hal/$(RTL871X)/$(RTL871X)_cmd.o \
            hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_halinit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_led.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_xmit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_recv.o
ifeq ($(CONFIG_SDIO_HCI), y)
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops.o
else
ifeq ($(CONFIG_GSPI_HCI), y)
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops.o
else
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops_linux.o
endif
endif
ifeq ($(CONFIG_RTL8812A), y)
ifeq ($(CONFIG_USB_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8812A_USB.o
endif
ifeq ($(CONFIG_PCI_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8812A_PCIE.o
endif
endif
ifeq ($(CONFIG_RTL8821A), y)
ifeq ($(CONFIG_USB_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8821A_USB.o
endif
ifeq ($(CONFIG_PCI_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8821A_PCIE.o
endif
endif
ifeq ($(CONFIG_RTL8812A), y)
EXTRA_CFLAGS += -DCONFIG_RTL8812A
_HAL_INTFS_FILES +=    hal/rtl8812a/hal8812a_fw.o
_OUTSRC_FILES += hal/phydm/$(RTL871X)/halhwimg8812a_mac.o\
        hal/phydm/$(RTL871X)/halhwimg8812a_bb.o\
        hal/phydm/$(RTL871X)/halhwimg8812a_rf.o\
        hal/phydm/$(RTL871X)/halphyrf_8812a_ce.o\
        hal/phydm/$(RTL871X)/phydm_regconfig8812a.o\
        hal/phydm/$(RTL871X)/phydm_rtl8812a.o\
        hal/phydm/txbf/haltxbfjaguar.o
endif
ifeq ($(CONFIG_RTL8821A), y)
ifeq ($(CONFIG_RTL8812A), n)
RTL871X = rtl8821a
ifeq ($(CONFIG_USB_HCI), y)
ifeq ($(CONFIG_BT_COEXIST), y)
MODULE_NAME := 8821au
else
MODULE_NAME := 8811au
endif
endif
ifeq ($(CONFIG_PCI_HCI), y)
MODULE_NAME := 8821ae
endif
ifeq ($(CONFIG_SDIO_HCI), y)
MODULE_NAME := 8821as
endif
endif
EXTRA_CFLAGS += -DCONFIG_RTL8821A
_HAL_INTFS_FILES +=    hal/rtl8812a/hal8821a_fw.o
_OUTSRC_FILES += hal/phydm/rtl8821a/halhwimg8821a_mac.o\
        hal/phydm/rtl8821a/halhwimg8821a_bb.o\
        hal/phydm/rtl8821a/halhwimg8821a_rf.o\
        hal/phydm/rtl8812a/halphyrf_8812a_ce.o\
        hal/phydm/rtl8821a/halphyrf_8821a_ce.o\
        hal/phydm/rtl8821a/phydm_regconfig8821a.o\
        hal/phydm/rtl8821a/phydm_rtl8821a.o\
        hal/phydm/rtl8821a/phydm_iqk_8821a_ce.o\
        hal/phydm/txbf/haltxbfjaguar.o
endif
endif
########### HAL_RTL8723B #################################
ifeq ($(CONFIG_RTL8723B), y)
RTL871X = rtl8723b
ifeq ($(CONFIG_USB_HCI), y)
MODULE_NAME = 8723bu
endif
ifeq ($(CONFIG_PCI_HCI), y)
MODULE_NAME = 8723be
endif
ifeq ($(CONFIG_SDIO_HCI), y)
MODULE_NAME = 8723bs
endif
EXTRA_CFLAGS += -DCONFIG_RTL8723B
_HAL_INTFS_FILES += hal/HalPwrSeqCmd.o \
                    hal/$(RTL871X)/Hal8723BPwrSeq.o\
                    hal/$(RTL871X)/$(RTL871X)_sreset.o
_HAL_INTFS_FILES +=    hal/$(RTL871X)/$(RTL871X)_hal_init.o \
            hal/$(RTL871X)/$(RTL871X)_phycfg.o \
            hal/$(RTL871X)/$(RTL871X)_rf6052.o \
            hal/$(RTL871X)/$(RTL871X)_dm.o \
            hal/$(RTL871X)/$(RTL871X)_rxdesc.o \
            hal/$(RTL871X)/$(RTL871X)_cmd.o \
            hal/$(RTL871X)/hal8723b_fw.o
_HAL_INTFS_FILES +=    \
            hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_halinit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_led.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_xmit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_recv.o
ifeq ($(CONFIG_PCI_HCI), y)
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops_linux.o
else
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops.o
endif
ifeq ($(CONFIG_USB_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8723B_USB.o
endif
ifeq ($(CONFIG_PCI_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8723B_PCIE.o
endif
_OUTSRC_FILES += hal/phydm/$(RTL871X)/halhwimg8723b_bb.o\
                                hal/phydm/$(RTL871X)/halhwimg8723b_mac.o\
                                hal/phydm/$(RTL871X)/halhwimg8723b_rf.o\
                                hal/phydm/$(RTL871X)/halhwimg8723b_mp.o\
                                hal/phydm/$(RTL871X)/phydm_regconfig8723b.o\
                                hal/phydm/$(RTL871X)/halphyrf_8723b_ce.o\
                                hal/phydm/$(RTL871X)/phydm_rtl8723b.o
endif
########### HAL_RTL8814A #################################
ifeq ($(CONFIG_RTL8814A), y)
## ADD NEW VHT MP HW TX MODE ##
#EXTRA_CFLAGS += -DCONFIG_MP_VHT_HW_TX_MODE
#CONFIG_MP_VHT_HW_TX_MODE = y
##########################################
RTL871X = rtl8814a
ifeq ($(CONFIG_USB_HCI), y)
MODULE_NAME = 8814au
endif
ifeq ($(CONFIG_PCI_HCI), y)
MODULE_NAME = 8814ae
endif
ifeq ($(CONFIG_SDIO_HCI), y)
MODULE_NAME = 8814as
endif
EXTRA_CFLAGS += -DCONFIG_RTL8814A
_HAL_INTFS_FILES +=  hal/HalPwrSeqCmd.o \
                    hal/$(RTL871X)/Hal8814PwrSeq.o \
                    hal/$(RTL871X)/$(RTL871X)_xmit.o\
                    hal/$(RTL871X)/$(RTL871X)_sreset.o
_HAL_INTFS_FILES +=    hal/$(RTL871X)/$(RTL871X)_hal_init.o \
            hal/$(RTL871X)/$(RTL871X)_phycfg.o \
            hal/$(RTL871X)/$(RTL871X)_rf6052.o \
            hal/$(RTL871X)/$(RTL871X)_dm.o \
            hal/$(RTL871X)/$(RTL871X)_rxdesc.o \
            hal/$(RTL871X)/$(RTL871X)_cmd.o \
            hal/$(RTL871X)/hal8814a_fw.o
_HAL_INTFS_FILES +=    \
            hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_halinit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_led.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_xmit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_recv.o
ifeq ($(CONFIG_SDIO_HCI), y)
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops.o
else
ifeq ($(CONFIG_GSPI_HCI), y)
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops.o
else
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops_linux.o
endif
endif
ifeq ($(CONFIG_USB_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8814A_USB.o
endif
ifeq ($(CONFIG_PCI_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8814A_PCIE.o
endif
_OUTSRC_FILES += hal/phydm/$(RTL871X)/halhwimg8814a_bb.o\
                                hal/phydm/$(RTL871X)/halhwimg8814a_mac.o\
                                hal/phydm/$(RTL871X)/halhwimg8814a_rf.o\
                                hal/phydm/$(RTL871X)/phydm_iqk_8814a.o\
                                hal/phydm/$(RTL871X)/phydm_regconfig8814a.o\
                                hal/phydm/$(RTL871X)/halphyrf_8814a_ce.o\
                                hal/phydm/$(RTL871X)/phydm_rtl8814a.o\
                                hal/phydm/txbf/haltxbf8814a.o
endif
########### HAL_RTL8723C #################################
ifeq ($(CONFIG_RTL8723C), y)
RTL871X = rtl8703b
ifeq ($(CONFIG_USB_HCI), y)
MODULE_NAME = 8723cu
MODULE_SUB_NAME = 8703bu
endif
ifeq ($(CONFIG_PCI_HCI), y)
MODULE_NAME = 8723ce
MODULE_SUB_NAME = 8703be
endif
ifeq ($(CONFIG_SDIO_HCI), y)
MODULE_NAME = 8723cs
MODULE_SUB_NAME = 8703bs
endif
EXTRA_CFLAGS += -DCONFIG_RTL8703B
_HAL_INTFS_FILES += hal/HalPwrSeqCmd.o \
                    hal/$(RTL871X)/Hal8703BPwrSeq.o\
                    hal/$(RTL871X)/$(RTL871X)_sreset.o
_HAL_INTFS_FILES +=    hal/$(RTL871X)/$(RTL871X)_hal_init.o \
            hal/$(RTL871X)/$(RTL871X)_phycfg.o \
            hal/$(RTL871X)/$(RTL871X)_rf6052.o \
            hal/$(RTL871X)/$(RTL871X)_dm.o \
            hal/$(RTL871X)/$(RTL871X)_rxdesc.o \
            hal/$(RTL871X)/$(RTL871X)_cmd.o \
            hal/$(RTL871X)/hal8703b_fw.o
_HAL_INTFS_FILES +=    \
            hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_halinit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_SUB_NAME)_led.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_SUB_NAME)_xmit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_SUB_NAME)_recv.o
ifeq ($(CONFIG_PCI_HCI), y)
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops_linux.o
else
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops.o
endif
ifeq ($(CONFIG_USB_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8703B_USB.o
endif
ifeq ($(CONFIG_PCI_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8703B_PCIE.o
endif
_OUTSRC_FILES += hal/phydm/$(RTL871X)/halhwimg8703b_bb.o\
                                hal/phydm/$(RTL871X)/halhwimg8703b_mac.o\
                                hal/phydm/$(RTL871X)/halhwimg8703b_rf.o\
                                hal/phydm/$(RTL871X)/phydm_regconfig8703b.o\
                                hal/phydm/$(RTL871X)/halphyrf_8703b.o
endif
########### HAL_RTL8723D #################################
ifeq ($(CONFIG_RTL8723D), y)
RTL871X = rtl8723d
ifeq ($(CONFIG_USB_HCI), y)
MODULE_NAME = 8723du
MODULE_SUB_NAME = 8723du
endif
ifeq ($(CONFIG_PCI_HCI), y)
MODULE_NAME = 8723de
MODULE_SUB_NAME = 8723de
endif
ifeq ($(CONFIG_SDIO_HCI), y)
MODULE_NAME = 8723ds
MODULE_SUB_NAME = 8723ds
endif
EXTRA_CFLAGS += -DCONFIG_RTL8723D
_HAL_INTFS_FILES += hal/HalPwrSeqCmd.o \
                    hal/$(RTL871X)/Hal8723DPwrSeq.o\
                    hal/$(RTL871X)/$(RTL871X)_sreset.o
_HAL_INTFS_FILES +=    hal/$(RTL871X)/$(RTL871X)_hal_init.o \
            hal/$(RTL871X)/$(RTL871X)_phycfg.o \
            hal/$(RTL871X)/$(RTL871X)_rf6052.o \
            hal/$(RTL871X)/$(RTL871X)_dm.o \
            hal/$(RTL871X)/$(RTL871X)_rxdesc.o \
            hal/$(RTL871X)/$(RTL871X)_cmd.o \
            hal/$(RTL871X)/hal8723d_fw.o \
            hal/$(RTL871X)/$(RTL871X)_lps_poff.o
_HAL_INTFS_FILES +=    \
            hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_halinit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_SUB_NAME)_led.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_SUB_NAME)_xmit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_SUB_NAME)_recv.o
ifeq ($(CONFIG_PCI_HCI), y)
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops_linux.o
else
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops.o
endif
ifeq ($(CONFIG_USB_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8723D_USB.o
endif
ifeq ($(CONFIG_PCI_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8723D_PCIE.o
endif
_OUTSRC_FILES += hal/phydm/$(RTL871X)/halhwimg8723d_bb.o\
                                hal/phydm/$(RTL871X)/halhwimg8723d_mac.o\
                                hal/phydm/$(RTL871X)/halhwimg8723d_rf.o\
                                hal/phydm/$(RTL871X)/phydm_regconfig8723d.o\
                                hal/phydm/$(RTL871X)/phydm_rtl8723d.o\
                                hal/phydm/$(RTL871X)/halphyrf_8723d.o
endif
########### HAL_RTL8188F #################################
ifeq ($(CONFIG_RTL8188F), y)
RTL871X = rtl8188f
ifeq ($(CONFIG_USB_HCI), y)
MODULE_NAME = 8188fu
endif
ifeq ($(CONFIG_PCI_HCI), y)
MODULE_NAME = 8188fe
endif
ifeq ($(CONFIG_SDIO_HCI), y)
MODULE_NAME = 8189fs
endif
EXTRA_CFLAGS += -DCONFIG_RTL8188F
_HAL_INTFS_FILES += hal/HalPwrSeqCmd.o \
                    hal/$(RTL871X)/Hal8188FPwrSeq.o\
                    hal/$(RTL871X)/$(RTL871X)_sreset.o
_HAL_INTFS_FILES +=    hal/$(RTL871X)/$(RTL871X)_hal_init.o \
            hal/$(RTL871X)/$(RTL871X)_phycfg.o \
            hal/$(RTL871X)/$(RTL871X)_rf6052.o \
            hal/$(RTL871X)/$(RTL871X)_dm.o \
            hal/$(RTL871X)/$(RTL871X)_rxdesc.o \
            hal/$(RTL871X)/$(RTL871X)_cmd.o \
            hal/$(RTL871X)/hal8188f_fw.o
_HAL_INTFS_FILES +=    \
            hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_halinit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_led.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_xmit.o \
            hal/$(RTL871X)/$(HCI_NAME)/rtl$(MODULE_NAME)_recv.o
ifeq ($(CONFIG_PCI_HCI), y)
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops_linux.o
else
_HAL_INTFS_FILES += hal/$(RTL871X)/$(HCI_NAME)/$(HCI_NAME)_ops.o
endif
ifeq ($(CONFIG_USB_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8188F_USB.o
endif
ifeq ($(CONFIG_SDIO_HCI), y)
_HAL_INTFS_FILES +=hal/efuse/$(RTL871X)/HalEfuseMask8188F_SDIO.o
endif
_OUTSRC_FILES += hal/phydm/$(RTL871X)/halhwimg8188f_bb.o\
                                hal/phydm/$(RTL871X)/halhwimg8188f_mac.o\
                                hal/phydm/$(RTL871X)/halhwimg8188f_rf.o\
                                hal/phydm/$(RTL871X)/phydm_regconfig8188f.o\
                                hal/phydm/$(RTL871X)/halphyrf_8188f.o \
                                hal/phydm/$(RTL871X)/phydm_rtl8188f.o
endif
########### HAL_RTL8822B #################################
ifeq ($(CONFIG_RTL8822B), y)
include $(TopDIR)/rtl8822b.mk
endif
########### HAL_RTL8821C #################################
ifeq ($(CONFIG_RTL8821C), y)
include $(TopDIR)/rtl8821c.mk
_OUTSRC_FILES +=    hal/phydm/rtl8821c/halhwimg8821c_bb.o \
            hal/phydm/rtl8821c/halhwimg8821c_mac.o \
            hal/phydm/rtl8821c/halhwimg8821c_rf.o \
            hal/phydm/rtl8821c/phydm_hal_api8821c.o \
            hal/phydm/rtl8821c/phydm_regconfig8821c.o\
            hal/phydm/rtl8821c/halphyrf_8821c.o\
            hal/phydm/rtl8821c/phydm_iqk_8821c.o
endif
########### AUTO_CFG  #################################
ifeq ($(CONFIG_AUTOCFG_CP), y)
ifeq ($(CONFIG_MULTIDRV), y)
$(shell cp $(TopDIR)/autoconf_multidrv_$(HCI_NAME)_linux.h $(TopDIR)/include/autoconf.h)
else
ifeq ($(CONFIG_RTL8188E)$(CONFIG_SDIO_HCI),yy)
$(shell cp $(TopDIR)/autoconf_rtl8189e_$(HCI_NAME)_linux.h $(TopDIR)/include/autoconf.h)
else ifeq ($(CONFIG_RTL8188F)$(CONFIG_SDIO_HCI),yy)
$(shell cp $(TopDIR)/autoconf_rtl8189f_$(HCI_NAME)_linux.h $(TopDIR)/include/autoconf.h)
else ifeq ($(CONFIG_RTL8723C),y)
$(shell cp $(TopDIR)/autoconf_rtl8723c_$(HCI_NAME)_linux.h $(TopDIR)/include/autoconf.h)
else
$(shell cp $(TopDIR)/autoconf_$(RTL871X)_$(HCI_NAME)_linux.h $(TopDIR)/include/autoconf.h)
endif
endif
endif
########### END OF PATH  #################################
ifeq ($(CONFIG_USB_HCI), y)
ifeq ($(CONFIG_USB_AUTOSUSPEND), y)
EXTRA_CFLAGS += -DCONFIG_USB_AUTOSUSPEND
endif
endif
ifeq ($(CONFIG_MP_INCLUDED), y)
#MODULE_NAME := $(MODULE_NAME)_mp
EXTRA_CFLAGS += -DCONFIG_MP_INCLUDED
endif
ifeq ($(CONFIG_POWER_SAVING), y)
EXTRA_CFLAGS += -DCONFIG_POWER_SAVING
endif
ifeq ($(CONFIG_HW_PWRP_DETECTION), y)
EXTRA_CFLAGS += -DCONFIG_HW_PWRP_DETECTION
endif
ifeq ($(CONFIG_WIFI_TEST), y)
EXTRA_CFLAGS += -DCONFIG_WIFI_TEST
endif
ifeq ($(CONFIG_BT_COEXIST), y)
EXTRA_CFLAGS += -DCONFIG_BT_COEXIST
endif
ifeq ($(CONFIG_INTEL_WIDI), y)
EXTRA_CFLAGS += -DCONFIG_INTEL_WIDI
endif
ifeq ($(CONFIG_WAPI_SUPPORT), y)
EXTRA_CFLAGS += -DCONFIG_WAPI_SUPPORT
endif
ifeq ($(CONFIG_EFUSE_CONFIG_FILE), y)
EXTRA_CFLAGS += -DCONFIG_EFUSE_CONFIG_FILE
#EFUSE_MAP_PATH
USER_EFUSE_MAP_PATH ?=
ifneq ($(USER_EFUSE_MAP_PATH),)
EXTRA_CFLAGS += -DEFUSE_MAP_PATH=\"$(USER_EFUSE_MAP_PATH)\"
else ifeq ($(MODULE_NAME), 8189es)
EXTRA_CFLAGS += -DEFUSE_MAP_PATH=\"/system/etc/wifi/wifi_efuse_8189e.map\"
else ifeq ($(MODULE_NAME), 8723bs)
EXTRA_CFLAGS += -DEFUSE_MAP_PATH=\"/system/etc/wifi/wifi_efuse_8723bs.map\"
else
EXTRA_CFLAGS += -DEFUSE_MAP_PATH=\"/system/etc/wifi/wifi_efuse_$(MODULE_NAME).map\"
endif
#WIFIMAC_PATH
USER_WIFIMAC_PATH ?=
ifneq ($(USER_WIFIMAC_PATH),)
EXTRA_CFLAGS += -DWIFIMAC_PATH=\"$(USER_WIFIMAC_PATH)\"
else
EXTRA_CFLAGS += -DWIFIMAC_PATH=\"/data/wifimac.txt\"
endif
endif
ifeq ($(CONFIG_EXT_CLK), y)
EXTRA_CFLAGS += -DCONFIG_EXT_CLK
endif
ifeq ($(CONFIG_TRAFFIC_PROTECT), y)
EXTRA_CFLAGS += -DCONFIG_TRAFFIC_PROTECT
endif
ifeq ($(CONFIG_LOAD_PHY_PARA_FROM_FILE), y)
EXTRA_CFLAGS += -DCONFIG_LOAD_PHY_PARA_FROM_FILE
#EXTRA_CFLAGS += -DREALTEK_CONFIG_PATH_WITH_IC_NAME_FOLDER
#EXTRA_CFLAGS += -DREALTEK_CONFIG_PATH=\"/lib/firmware/\"
EXTRA_CFLAGS += -DREALTEK_CONFIG_PATH=\"\"
endif
ifeq ($(CONFIG_TXPWR_BY_RATE_EN), n)
EXTRA_CFLAGS += -DCONFIG_TXPWR_BY_RATE_EN=0
else ifeq ($(CONFIG_TXPWR_BY_RATE_EN), y)
EXTRA_CFLAGS += -DCONFIG_TXPWR_BY_RATE_EN=1
else ifeq ($(CONFIG_TXPWR_BY_RATE_EN), auto)
EXTRA_CFLAGS += -DCONFIG_TXPWR_BY_RATE_EN=2
endif
ifeq ($(CONFIG_TXPWR_LIMIT_EN), n)
EXTRA_CFLAGS += -DCONFIG_TXPWR_LIMIT_EN=0
else ifeq ($(CONFIG_TXPWR_LIMIT_EN), y)
EXTRA_CFLAGS += -DCONFIG_TXPWR_LIMIT_EN=1
else ifeq ($(CONFIG_TXPWR_LIMIT_EN), auto)
EXTRA_CFLAGS += -DCONFIG_TXPWR_LIMIT_EN=2
endif
ifeq ($(CONFIG_CALIBRATE_TX_POWER_BY_REGULATORY), y)
EXTRA_CFLAGS += -DCONFIG_CALIBRATE_TX_POWER_BY_REGULATORY
endif
ifeq ($(CONFIG_CALIBRATE_TX_POWER_TO_MAX), y)
EXTRA_CFLAGS += -DCONFIG_CALIBRATE_TX_POWER_TO_MAX
endif
ifeq ($(CONFIG_RTW_ADAPTIVITY_EN), disable)
EXTRA_CFLAGS += -DCONFIG_RTW_ADAPTIVITY_EN=0
else ifeq ($(CONFIG_RTW_ADAPTIVITY_EN), enable)
EXTRA_CFLAGS += -DCONFIG_RTW_ADAPTIVITY_EN=1
endif
ifeq ($(CONFIG_RTW_ADAPTIVITY_MODE), normal)
EXTRA_CFLAGS += -DCONFIG_RTW_ADAPTIVITY_MODE=0
else ifeq ($(CONFIG_RTW_ADAPTIVITY_MODE), carrier_sense)
EXTRA_CFLAGS += -DCONFIG_RTW_ADAPTIVITY_MODE=1
endif
ifeq ($(CONFIG_SIGNAL_SCALE_MAPPING), y)
EXTRA_CFLAGS += -DCONFIG_SIGNAL_SCALE_MAPPING
endif
ifeq ($(CONFIG_80211W), y)
EXTRA_CFLAGS += -DCONFIG_IEEE80211W
endif
ifeq ($(CONFIG_WOWLAN), y)
EXTRA_CFLAGS += -DCONFIG_WOWLAN
ifeq ($(CONFIG_SDIO_HCI), y)
EXTRA_CFLAGS += -DCONFIG_RTW_SDIO_PM_KEEP_POWER
endif
ifeq ($(CONFIG_DEFAULT_PATTERNS_EN), y)
EXTRA_CFLAGS += -DCONFIG_DEFAULT_PATTERNS_EN
endif
endif
ifeq ($(CONFIG_AP_WOWLAN), y)
EXTRA_CFLAGS += -DCONFIG_AP_WOWLAN
ifeq ($(CONFIG_SDIO_HCI), y)
EXTRA_CFLAGS += -DCONFIG_RTW_SDIO_PM_KEEP_POWER
endif
endif
ifeq ($(CONFIG_PNO_SUPPORT), y)
EXTRA_CFLAGS += -DCONFIG_PNO_SUPPORT
ifeq ($(CONFIG_PNO_SET_DEBUG), y)
EXTRA_CFLAGS += -DCONFIG_PNO_SET_DEBUG
endif
endif
ifeq ($(CONFIG_GPIO_WAKEUP), y)
EXTRA_CFLAGS += -DCONFIG_GPIO_WAKEUP
ifeq ($(CONFIG_HIGH_ACTIVE), y)
EXTRA_CFLAGS += -DHIGH_ACTIVE=1
else
EXTRA_CFLAGS += -DHIGH_ACTIVE=0
endif
endif
ifneq ($(CONFIG_WAKEUP_GPIO_IDX), default)
EXTRA_CFLAGS += -DWAKEUP_GPIO_IDX=$(CONFIG_WAKEUP_GPIO_IDX)
endif
ifeq ($(CONFIG_RTW_SDIO_PM_KEEP_POWER), y)
ifeq ($(CONFIG_SDIO_HCI), y)
EXTRA_CFLAGS += -DCONFIG_RTW_SDIO_PM_KEEP_POWER
endif
endif
ifeq ($(CONFIG_REDUCE_TX_CPU_LOADING), y)
EXTRA_CFLAGS += -DCONFIG_REDUCE_TX_CPU_LOADING
endif
ifeq ($(CONFIG_BR_EXT), y)
BR_NAME = br0
EXTRA_CFLAGS += -DCONFIG_BR_EXT
EXTRA_CFLAGS += '-DCONFIG_BR_EXT_BRNAME="'$(BR_NAME)'"'
endif
ifeq ($(CONFIG_TDLS), y)
EXTRA_CFLAGS += -DCONFIG_TDLS
endif
ifeq ($(CONFIG_WIFI_MONITOR), y)
EXTRA_CFLAGS += -DCONFIG_WIFI_MONITOR
endif
ifeq ($(CONFIG_MCC_MODE), y)
EXTRA_CFLAGS += -DCONFIG_MCC_MODE
endif
ifeq ($(CONFIG_RTW_NAPI), y)
EXTRA_CFLAGS += -DCONFIG_RTW_NAPI
endif
ifeq ($(CONFIG_RTW_GRO), y)
EXTRA_CFLAGS += -DCONFIG_RTW_GRO
endif
ifeq ($(CONFIG_MP_VHT_HW_TX_MODE), y)
EXTRA_CFLAGS += -DCONFIG_MP_VHT_HW_TX_MODE
ifeq ($(CONFIG_PLATFORM_I386_PC), y)
## For I386 X86 ToolChain use Hardware FLOATING
EXTRA_CFLAGS += -mhard-float
else
## For ARM ToolChain use Hardware FLOATING
EXTRA_CFLAGS += -mfloat-abi=hard
endif
endif
ifeq ($(CONFIG_APPEND_VENDOR_IE_ENABLE), y)
EXTRA_CFLAGS += -DCONFIG_APPEND_VENDOR_IE_ENABLE
endif
ifeq ($(CONFIG_RTW_DEBUG), y)
EXTRA_CFLAGS += -DCONFIG_RTW_DEBUG
EXTRA_CFLAGS += -DRTW_LOG_LEVEL=$(CONFIG_RTW_LOG_LEVEL)
endif
EXTRA_CFLAGS += -DDM_ODM_SUPPORT_TYPE=0x04
ifeq ($(CONFIG_PLATFORM_I386_PC), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/)
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?=
KVER  := $(shell uname -r)
KSRC := /lib/modules/$(KVER)/build
MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless/
INSTALL_PREFIX :=
endif
ifeq ($(CONFIG_PLATFORM_ARM_SAMA5D4), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
ARCH := arm
CROSS_COMPILE := /opt/buildroot/cortex-a5/bin/arm-linux-
KVER  := 4.9.151
KSRC ?= ../../linux-at91/
endif
ifeq ($(CONFIG_PLATFORM_BCM2709), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
ARCH ?= arm
CROSS_COMPILE ?=
KVER  := $(shell uname -r)
KSRC := /lib/modules/$(KVER)/build
MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless/
INSTALL_PREFIX :=
endif
ifeq ($(CONFIG_PLATFORM_NV_TK1), y)
EXTRA_CFLAGS += -DCONFIG_PLATFORM_NV_TK1
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
ARCH ?= arm
CROSS_COMPILE ?=
KVER := $(shell uname -r)
KSRC := /lib/modules/$(KVER)/build
MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless/
INSTALL_PREFIX :=
endif
ifeq ($(CONFIG_PLATFORM_ACTIONS_ATM702X), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_ANDROID -DCONFIG_PLATFORM_ACTIONS_ATM702X
#ARCH := arm
ARCH := $(R_ARCH)
#CROSS_COMPILE := arm-none-linux-gnueabi-
CROSS_COMPILE := $(R_CROSS_COMPILE)
KVER:= 3.4.0
#KSRC := ../../../../build/out/kernel
KSRC := $(KERNEL_BUILD_PATH)
MODULE_NAME :=wlan
endif
ifeq ($(CONFIG_PLATFORM_ACTIONS_ATM705X), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
#EXTRA_CFLAGS += -DRTW_ENABLE_WIFI_CONTROL_FUNC
# default setting for Android 4.1, 4.2, 4.3, 4.4
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ACTIONS_ATM705X
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
# Enable this for Android 5.0
EXTRA_CFLAGS += -DCONFIG_RADIO_WORK
ifeq ($(CONFIG_SDIO_HCI), y)
EXTRA_CFLAGS += -DCONFIG_PLATFORM_OPS
_PLATFORM_FILES += platform/platform_arm_act_sdio.o
endif
ARCH := arm
CROSS_COMPILE := /opt/arm-2011.09/bin/arm-none-linux-gnueabi-
KSRC := /home/android_sdk/Action-semi/705a_android_L/android/kernel
endif
ifeq ($(CONFIG_PLATFORM_ARM_SUN50IW1P1), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ARM_SUN50IW1P1
EXTRA_CFLAGS += -DCONFIG_TRAFFIC_PROTECT
# default setting for Android 4.1, 4.2
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
EXTRA_CFLAGS += -DCONFIG_RESUME_IN_WORKQUEUE
EXTRA_CFLAGS += -DCONFIG_PLATFORM_OPS
# Enable this for Android 5.0
EXTRA_CFLAGS += -DCONFIG_RADIO_WORK
ifeq ($(CONFIG_USB_HCI), y)
EXTRA_CFLAGS += -DCONFIG_USE_USB_BUFFER_ALLOC_TX
_PLATFORM_FILES += platform/platform_ARM_SUNxI_usb.o
endif
ifeq ($(CONFIG_SDIO_HCI), y)
_PLATFORM_FILES += platform/platform_ARM_SUN50IW1P1_sdio.o
endif
ARCH := arm64
# ===Cross compile setting for Android 5.1(64) SDK ===
CROSS_COMPILE := /home/android_sdk/Allwinner/a64/android-51/lichee/out/sun50iw1p1/android/common/buildroot/external-toolchain/bin/aarch64-linux-gnu-
KSRC :=/home/android_sdk/Allwinner/a64/android-51/lichee/linux-3.10/
endif
ifeq ($(CONFIG_PLATFORM_TI_AM3517), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_ANDROID -DCONFIG_PLATFORM_SHUTTLE
CROSS_COMPILE := arm-eabi-
KSRC := $(shell pwd)/../../../Android/kernel
ARCH := arm
endif
ifeq ($(CONFIG_PLATFORM_MSTAR_TITANIA12), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_MSTAR -DCONFIG_PLATFORM_MSTAR_TITANIA12
ARCH:=mips
CROSS_COMPILE:= /usr/src/Mstar_kernel/mips-4.3/bin/mips-linux-gnu-
KVER:= 2.6.28.9
KSRC:= /usr/src/Mstar_kernel/2.6.28.9/
endif
ifeq ($(CONFIG_PLATFORM_MSTAR), y)
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_MSTAR -DCONFIG_USE_USB_BUFFER_ALLOC_TX -DCONFIG_FIX_NR_BULKIN_BUFFER
EXTRA_CFLAGS += -DCONFIG_PLATFORM_MSTAR_HIGH
ARCH:=arm
CROSS_COMPILE:= /usr/src/bin/arm-none-linux-gnueabi-
KVER:= 3.1.10
KSRC:= /usr/src/Mstar_kernel/3.1.10/
endif
ifeq ($(CONFIG_PLATFORM_ANDROID_X86), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/)
ARCH := $(SUBARCH)
CROSS_COMPILE := /media/DATA-2/android-x86/ics-x86_20120130/prebuilt/linux-x86/toolchain/i686-unknown-linux-gnu-4.2.1/bin/i686-unknown-linux-gnu-
KSRC := /media/DATA-2/android-x86/ics-x86_20120130/out/target/product/generic_x86/obj/kernel
MODULE_NAME :=wlan
endif
ifeq ($(CONFIG_PLATFORM_ANDROID_X86_N70), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
EXTRA_CFLAGS += -DCONFIG_RADIO_WORK
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ANDROID
ARCH := x86
#CROSS_COMPILE := /work/android-x86/android-x86/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7/bin/i686-linux-android-
CROSS_COMPILE := /home/work/android-N/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin/x86_64-linux-android-
#CROSS_COMPILE :=          /work/78/android-x86/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin/x86_64-linux-android-
KSRC := /home/work/android-N/out/target/product/x86/obj/kernel/
#KSRC :=          /work/78/android-x86/out/target/product/x86/obj/kernel/
MODULE_NAME :=wlan-8188ee
endif
ifeq ($(CONFIG_PLATFORM_ANDROID_INTEL_X86), y)
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ANDROID_INTEL_X86
EXTRA_CFLAGS += -DCONFIG_PLATFORM_INTEL_BYT
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_ANDROID
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
EXTRA_CFLAGS += -DCONFIG_SKIP_SIGNAL_SCALE_MAPPING
ifeq ($(CONFIG_SDIO_HCI), y)
EXTRA_CFLAGS += -DCONFIG_RESUME_IN_WORKQUEUE
endif
endif
ifeq ($(CONFIG_PLATFORM_JB_X86), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/)
ARCH := $(SUBARCH)
CROSS_COMPILE := /home/android_sdk/android-x86_JB/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7/bin/i686-linux-android-
KSRC := /home/android_sdk/android-x86_JB/out/target/product/x86/obj/kernel/
MODULE_NAME :=wlan
endif
ifeq ($(CONFIG_PLATFORM_ARM_PXA2XX), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ARCH := arm
CROSS_COMPILE := arm-none-linux-gnueabi-
KVER  := 2.6.34.1
KSRC ?= /usr/src/linux-2.6.34.1
endif
ifeq ($(CONFIG_PLATFORM_ARM_S3C2K4), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ARCH := arm
CROSS_COMPILE := arm-linux-
KVER  := 2.6.24.7_$(ARCH)
KSRC := /usr/src/kernels/linux-$(KVER)
endif
ifeq ($(CONFIG_PLATFORM_ARM_S3C6K4), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ARCH := arm
CROSS_COMPILE := arm-none-linux-gnueabi-
KVER  := 2.6.34.1
KSRC ?= /usr/src/linux-2.6.34.1
endif
ifeq ($(CONFIG_PLATFORM_RTD2880B), y)
EXTRA_CFLAGS += -DCONFIG_BIG_ENDIAN -DCONFIG_PLATFORM_RTD2880B
ARCH:=
CROSS_COMPILE:=
KVER:=
KSRC:=
endif
ifeq ($(CONFIG_PLATFORM_MIPS_RMI), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ARCH:=mips
CROSS_COMPILE:=mipsisa32r2-uclibc-
KVER:=
KSRC:= /root/work/kernel_realtek
endif
ifeq ($(CONFIG_PLATFORM_MIPS_PLM), y)
EXTRA_CFLAGS += -DCONFIG_BIG_ENDIAN
ARCH:=mips
CROSS_COMPILE:=mipsisa32r2-uclibc-
KVER:=
KSRC:= /root/work/kernel_realtek
endif
ifeq ($(CONFIG_PLATFORM_MSTAR389), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_MSTAR389
ARCH:=mips
CROSS_COMPILE:= mips-linux-gnu-
KVER:= 2.6.28.10
KSRC:= /home/mstar/mstar_linux/2.6.28.9/
endif
ifeq ($(CONFIG_PLATFORM_MIPS_AR9132), y)
EXTRA_CFLAGS += -DCONFIG_BIG_ENDIAN
ARCH := mips
CROSS_COMPILE := mips-openwrt-linux-
KSRC := /home/alex/test_openwrt/tmp/linux-2.6.30.9
endif
ifeq ($(CONFIG_PLATFORM_DMP_PHILIPS), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DRTK_DMP_PLATFORM
ARCH := mips
#CROSS_COMPILE:=/usr/local/msdk-4.3.6-mips-EL-2.6.12.6-0.9.30.3/bin/mipsel-linux-
CROSS_COMPILE:=/usr/local/toolchain_mipsel/bin/mipsel-linux-
KSRC ?=/usr/local/Jupiter/linux-2.6.12
endif
ifeq ($(CONFIG_PLATFORM_RTK_DMP), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DRTK_DMP_PLATFORM  -DCONFIG_WIRELESS_EXT
EXTRA_CFLAGS += -DCONFIG_PLATFORM_OPS
ifeq ($(CONFIG_USB_HCI), y)
_PLATFORM_FILES += platform/platform_RTK_DMP_usb.o
endif
ARCH:=mips
CROSS_COMPILE:=mipsel-linux-
KVER:=
KSRC ?= /usr/src/DMP_Kernel/jupiter/linux-2.6.12
endif
ifeq ($(CONFIG_PLATFORM_MT53XX), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_MT53XX
ARCH:= arm
CROSS_COMPILE:= arm11_mtk_le-
KVER:= 2.6.27
KSRC?= /proj/mtk00802/BD_Compare/BDP/Dev/BDP_V301/BDP_Linux/linux-2.6.27
endif
ifeq ($(CONFIG_PLATFORM_ARM_MX51_241H), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_WISTRON_PLATFORM
ARCH := arm
CROSS_COMPILE := /opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-
KVER  := 2.6.31
KSRC ?= /lib/modules/2.6.31-770-g0e46b52/source
endif
ifeq ($(CONFIG_PLATFORM_FS_MX61), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ARCH := arm
CROSS_COMPILE := /home/share/CusEnv/FreeScale/arm-eabi-4.4.3/bin/arm-eabi-
KSRC ?= /home/share/CusEnv/FreeScale/FS_kernel_env
endif
ifeq ($(CONFIG_PLATFORM_ACTIONS_ATJ227X), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_ACTIONS_ATJ227X
ARCH := mips
CROSS_COMPILE := /home/cnsd4/project/actions/tools-2.6.27/bin/mipsel-linux-gnu-
KVER  := 2.6.27
KSRC := /home/cnsd4/project/actions/linux-2.6.27.28
endif
ifeq ($(CONFIG_PLATFORM_TI_DM365), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_TI_DM365
EXTRA_CFLAGS += -DCONFIG_USE_USB_BUFFER_ALLOC_RX
EXTRA_CFLAGS += -DCONFIG_SINGLE_XMIT_BUF -DCONFIG_SINGLE_RECV_BUF
ARCH := arm
#CROSS_COMPILE := /home/cnsd4/Appro/mv_pro_5.0/montavista/pro/devkit/arm/v5t_le/bin/arm_v5t_le-
#KSRC := /home/cnsd4/Appro/mv_pro_5.0/montavista/pro/devkit/lsp/ti-davinci/linux-dm365
CROSS_COMPILE := /opt/montavista/pro5.0/devkit/arm/v5t_le/bin/arm-linux-
KSRC:= /home/vivotek/lsp/DM365/kernel_platform/kernel/linux-2.6.18
KERNELOUTPUT := ${PRODUCTDIR}/tmp
KVER  := 2.6.18
endif
ifeq ($(CONFIG_PLATFORM_MOZART), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_MOZART
ARCH := arm
CROSS_COMPILE := /home/vivotek/lsp/mozart3v2/Mozart3e_Toolchain/build_arm_nofpu/usr/bin/arm-linux-
KVER  := $(shell uname -r)
KSRC:= /opt/Vivotek/lsp/mozart3v2/kernel_platform/kernel/mozart_kernel-1.17
KERNELOUTPUT := /home/pink/sample/ODM/IP8136W-VINT/tmp/kernel
endif
ifeq ($(CONFIG_PLATFORM_TEGRA3_CARDHU), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
# default setting for Android 4.1, 4.2
EXTRA_CFLAGS += -DRTW_ENABLE_WIFI_CONTROL_FUNC
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
ARCH := arm
CROSS_COMPILE := /home/android_sdk/nvidia/tegra-16r3-partner-android-4.1_20120723/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-
KSRC := /home/android_sdk/nvidia/tegra-16r3-partner-android-4.1_20120723/out/target/product/cardhu/obj/KERNEL
MODULE_NAME := wlan
endif
ifeq ($(CONFIG_PLATFORM_TEGRA4_DALMORE), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
# default setting for Android 4.1, 4.2
EXTRA_CFLAGS += -DRTW_ENABLE_WIFI_CONTROL_FUNC
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
ARCH := arm
CROSS_COMPILE := /home/android_sdk/nvidia/tegra-17r9-partner-android-4.2-dalmore_20130131/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
KSRC := /home/android_sdk/nvidia/tegra-17r9-partner-android-4.2-dalmore_20130131/out/target/product/dalmore/obj/KERNEL
MODULE_NAME := wlan
endif
ifeq ($(CONFIG_PLATFORM_ARM_TCC8900), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ARCH := arm
CROSS_COMPILE := /home/android_sdk/Telechips/SDK_2304_20110613/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-
KSRC := /home/android_sdk/Telechips/SDK_2304_20110613/kernel
MODULE_NAME := wlan
endif
ifeq ($(CONFIG_PLATFORM_ARM_TCC8920), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ARCH := arm
CROSS_COMPILE := /home/android_sdk/Telechips/v12.06_r1-tcc-android-4.0.4/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-
KSRC := /home/android_sdk/Telechips/v12.06_r1-tcc-android-4.0.4/kernel
MODULE_NAME := wlan
endif
ifeq ($(CONFIG_PLATFORM_ARM_TCC8920_JB42), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
# default setting for Android 4.1, 4.2
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
ARCH := arm
CROSS_COMPILE := /home/android_sdk/Telechips/v13.03_r1-tcc-android-4.2.2_ds_patched/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
KSRC := /home/android_sdk/Telechips/v13.03_r1-tcc-android-4.2.2_ds_patched/kernel
MODULE_NAME := wlan
endif
ifeq ($(CONFIG_PLATFORM_ARM_RK2818), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_ANDROID -DCONFIG_PLATFORM_ROCKCHIPS
ARCH := arm
CROSS_COMPILE := /usr/src/release_fae_version/toolchain/arm-eabi-4.4.0/bin/arm-eabi-
KSRC := /usr/src/release_fae_version/kernel25_A7_281x
MODULE_NAME := wlan
endif
ifeq ($(CONFIG_PLATFORM_ARM_RK3188), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_ANDROID -DCONFIG_PLATFORM_ROCKCHIPS
# default setting for Android 4.1, 4.2, 4.3, 4.4
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
# default setting for Power control
EXTRA_CFLAGS += -DRTW_ENABLE_WIFI_CONTROL_FUNC
EXTRA_CFLAGS += -DRTW_SUPPORT_PLATFORM_SHUTDOWN
# default setting for Special function
ARCH := arm
CROSS_COMPILE := /home/android_sdk/Rockchip/Rk3188/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
KSRC := /home/android_sdk/Rockchip/Rk3188/kernel
MODULE_NAME := wlan
endif
ifeq ($(CONFIG_PLATFORM_ARM_RK3066), y)
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ARM_RK3066
EXTRA_CFLAGS += -DRTW_ENABLE_WIFI_CONTROL_FUNC
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211
ifeq ($(CONFIG_SDIO_HCI), y)
EXTRA_CFLAGS += -DRTW_SUPPORT_PLATFORM_SHUTDOWN
endif
EXTRA_CFLAGS += -fno-pic
ARCH := arm
CROSS_COMPILE := /home/android_sdk/Rockchip/rk3066_20130607/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/bin/arm-linux-androideabi-
#CROSS_COMPILE := /home/android_sdk/Rockchip/Rk3066sdk/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/bin/arm-linux-androideabi-
KSRC := /home/android_sdk/Rockchip/Rk3066sdk/kernel
MODULE_NAME :=wlan
endif
ifeq ($(CONFIG_PLATFORM_ARM_URBETTER), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN #-DCONFIG_MINIMAL_MEMORY_USAGE
ARCH := arm
CROSS_COMPILE := /media/DATA-1/urbetter/arm-2009q3/bin/arm-none-linux-gnueabi-
KSRC := /media/DATA-1/urbetter/ics-urbetter/kernel
MODULE_NAME := wlan
endif
ifeq ($(CONFIG_PLATFORM_ARM_TI_PANDA), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN #-DCONFIG_MINIMAL_MEMORY_USAGE
ARCH := arm
#CROSS_COMPILE := /media/DATA-1/aosp/ics-aosp_20111227/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-
#KSRC := /media/DATA-1/aosp/android-omap-panda-3.0_20120104
CROSS_COMPILE := /media/DATA-1/android-4.0/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-
KSRC := /media/DATA-1/android-4.0/panda_kernel/omap
MODULE_NAME := wlan
endif
ifeq ($(CONFIG_PLATFORM_MIPS_JZ4760), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_MINIMAL_MEMORY_USAGE
ARCH ?= mips
CROSS_COMPILE ?= /mnt/sdb5/Ingenic/Umido/mips-4.3/bin/mips-linux-gnu-
KSRC ?= /mnt/sdb5/Ingenic/Umido/kernel
endif
ifeq ($(CONFIG_PLATFORM_SZEBOOK), y)
EXTRA_CFLAGS += -DCONFIG_BIG_ENDIAN
ARCH:=arm
CROSS_COMPILE:=/opt/crosstool2/bin/armeb-unknown-linux-gnueabi-
KVER:= 2.6.31.6
KSRC:= ../code/linux-2.6.31.6-2020/
endif
#Add setting for MN10300
ifeq ($(CONFIG_PLATFORM_MN10300), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_MN10300
ARCH := mn10300
CROSS_COMPILE := mn10300-linux-
KVER := 2.6.32.2
KSRC := /home/winuser/work/Plat_sLD2T_V3010/usr/src/linux-2.6.32.2
INSTALL_PREFIX :=
endif
ifeq ($(CONFIG_PLATFORM_ARM_SUNxI), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ARM_SUNxI
# default setting for Android 4.1, 4.2
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
EXTRA_CFLAGS += -DCONFIG_PLATFORM_OPS
ifeq ($(CONFIG_USB_HCI), y)
EXTRA_CFLAGS += -DCONFIG_USE_USB_BUFFER_ALLOC_TX
_PLATFORM_FILES += platform/platform_ARM_SUNxI_usb.o
endif
ifeq ($(CONFIG_SDIO_HCI), y)
# default setting for A10-EVB mmc0
#EXTRA_CFLAGS += -DCONFIG_WITS_EVB_V13
_PLATFORM_FILES += platform/platform_ARM_SUNxI_sdio.o
endif
ARCH := arm
#CROSS_COMPILE := arm-none-linux-gnueabi-
CROSS_COMPILE=/home/android_sdk/Allwinner/a10/android-jb42/lichee-jb42/buildroot/output/external-toolchain/bin/arm-none-linux-gnueabi-
KVER  := 3.0.8
#KSRC:= ../lichee/linux-3.0/
KSRC=/home/android_sdk/Allwinner/a10/android-jb42/lichee-jb42/linux-3.0
endif
ifeq ($(CONFIG_PLATFORM_ARM_SUN6I), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ARM_SUN6I
EXTRA_CFLAGS += -DCONFIG_TRAFFIC_PROTECT
# default setting for Android 4.1, 4.2, 4.3, 4.4
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
EXTRA_CFLAGS +=  -DCONFIG_QOS_OPTIMIZATION
EXTRA_CFLAGS += -DCONFIG_PLATFORM_OPS
ifeq ($(CONFIG_USB_HCI), y)
EXTRA_CFLAGS += -DCONFIG_USE_USB_BUFFER_ALLOC_TX
_PLATFORM_FILES += platform/platform_ARM_SUNxI_usb.o
endif
ifeq ($(CONFIG_SDIO_HCI), y)
# default setting for A31-EVB mmc0
EXTRA_CFLAGS += -DCONFIG_A31_EVB
_PLATFORM_FILES += platform/platform_ARM_SUNnI_sdio.o
endif
ARCH := arm
#Android-JB42
#CROSS_COMPILE := /home/android_sdk/Allwinner/a31/android-jb42/lichee/buildroot/output/external-toolchain/bin/arm-linux-gnueabi-
#KSRC :=/home/android_sdk/Allwinner/a31/android-jb42/lichee/linux-3.3
#ifeq ($(CONFIG_USB_HCI), y)
#MODULE_NAME := 8188eu_sw
#endif
# ==== Cross compile setting for kitkat-a3x_v4.5 =====
CROSS_COMPILE := /home/android_sdk/Allwinner/a31/kitkat-a3x_v4.5/lichee/buildroot/output/external-toolchain/bin/arm-linux-gnueabi-
KSRC :=/home/android_sdk/Allwinner/a31/kitkat-a3x_v4.5/lichee/linux-3.3
endif
ifeq ($(CONFIG_PLATFORM_ARM_SUN7I), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ARM_SUN7I
EXTRA_CFLAGS += -DCONFIG_TRAFFIC_PROTECT
# default setting for Android 4.1, 4.2, 4.3, 4.4
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
EXTRA_CFLAGS +=  -DCONFIG_QOS_OPTIMIZATION
EXTRA_CFLAGS += -DCONFIG_PLATFORM_OPS
ifeq ($(CONFIG_USB_HCI), y)
EXTRA_CFLAGS += -DCONFIG_USE_USB_BUFFER_ALLOC_TX
_PLATFORM_FILES += platform/platform_ARM_SUNxI_usb.o
endif
ifeq ($(CONFIG_SDIO_HCI), y)
_PLATFORM_FILES += platform/platform_ARM_SUNnI_sdio.o
endif
ARCH := arm
# ===Cross compile setting for Android 4.2 SDK ===
#CROSS_COMPILE := /home/android_sdk/Allwinner/a20_evb/lichee/out/android/common/buildroot/external-toolchain/bin/arm-linux-gnueabi-
#KSRC := /home/android_sdk/Allwinner/a20_evb/lichee/linux-3.3
# ==== Cross compile setting for Android 4.3 SDK =====
#CROSS_COMPILE := /home/android_sdk/Allwinner/a20/android-jb43/lichee/out/android/common/buildroot/external-toolchain/bin/arm-linux-gnueabi-
#KSRC := /home/android_sdk/Allwinner/a20/android-jb43/lichee/linux-3.4
# ==== Cross compile setting for kitkat-a20_v4.4 =====
CROSS_COMPILE := /home/android_sdk/Allwinner/a20/kitkat-a20_v4.4/lichee/out/android/common/buildroot/external-toolchain/bin/arm-linux-gnueabi-
KSRC := /home/android_sdk/Allwinner/a20/kitkat-a20_v4.4/lichee/linux-3.4
endif
ifeq ($(CONFIG_PLATFORM_ARM_SUN8I_W3P1), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ARM_SUN8I
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ARM_SUN8I_W3P1
EXTRA_CFLAGS += -DCONFIG_TRAFFIC_PROTECT
# default setting for Android 4.1, 4.2
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
EXTRA_CFLAGS += -DCONFIG_PLATFORM_OPS
ifeq ($(CONFIG_USB_HCI), y)
EXTRA_CFLAGS += -DCONFIG_USE_USB_BUFFER_ALLOC_TX
_PLATFORM_FILES += platform/platform_ARM_SUNxI_usb.o
endif
ifeq ($(CONFIG_SDIO_HCI), y)
_PLATFORM_FILES += platform/platform_ARM_SUNnI_sdio.o
endif
ARCH := arm
# ===Cross compile setting for Android 4.2 SDK ===
#CROSS_COMPILE := /home/android_sdk/Allwinner/a23/android-jb42/lichee/out/android/common/buildroot/external-toolchain/bin/arm-linux-gnueabi-
#KSRC :=/home/android_sdk/Allwinner/a23/android-jb42/lichee/linux-3.4
# ===Cross compile setting for Android 4.4 SDK ===
CROSS_COMPILE := /home/android_sdk/Allwinner/a23/android-kk44/lichee/out/android/common/buildroot/external-toolchain/bin/arm-linux-gnueabi-
KSRC :=/home/android_sdk/Allwinner/a23/android-kk44/lichee/linux-3.4
endif
ifeq ($(CONFIG_PLATFORM_ARM_SUN8I_W5P1), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ARM_SUN8I
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ARM_SUN8I_W5P1
EXTRA_CFLAGS += -DCONFIG_TRAFFIC_PROTECT
# default setting for Android 4.1, 4.2
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
# Enable this for Android 5.0
EXTRA_CFLAGS += -DCONFIG_RADIO_WORK
EXTRA_CFLAGS += -DCONFIG_PLATFORM_OPS
ifeq ($(CONFIG_USB_HCI), y)
EXTRA_CFLAGS += -DCONFIG_USE_USB_BUFFER_ALLOC_TX
_PLATFORM_FILES += platform/platform_ARM_SUNxI_usb.o
endif
ifeq ($(CONFIG_SDIO_HCI), y)
_PLATFORM_FILES += platform/platform_ARM_SUNnI_sdio.o
endif
ARCH := arm
# ===Cross compile setting for Android L SDK ===
CROSS_COMPILE := /home/android_sdk/Allwinner/a33/android-L/lichee/out/sun8iw5p1/android/common/buildroot/external-toolchain/bin/arm-linux-gnueabi-
KSRC :=/home/android_sdk/Allwinner/a33/android-L/lichee/linux-3.4
endif
ifeq ($(CONFIG_PLATFORM_ACTIONS_ATV5201), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_ACTIONS_ATV5201
EXTRA_CFLAGS += -DCONFIG_SDIO_DISABLE_RXFIFO_POLLING_LOOP
ARCH := mips
CROSS_COMPILE := mipsel-linux-gnu-
KVER  := $(KERNEL_VER)
KSRC:= $(CFGDIR)/../../kernel/linux-$(KERNEL_VER)
endif
ifeq ($(CONFIG_PLATFORM_ARM_RTD299X), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DUSB_XMITBUF_ALIGN_SZ=1024 -DUSB_PACKET_OFFSET_SZ=0
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
ifeq ($(CONFIG_ANDROID), y)
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
# Enable this for Android 5.0
EXTRA_CFLAGS += -DCONFIG_RADIO_WORK
endif
#ARCH, CROSS_COMPILE, KSRC,and  MODDESTDIR are provided by external makefile
INSTALL_PREFIX :=
endif
ifeq ($(CONFIG_PLATFORM_HISILICON), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN -DCONFIG_PLATFORM_HISILICON
ifeq ($(SUPPORT_CONCURRENT),y)
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
endif
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
ARCH := arm
ifeq ($(CROSS_COMPILE),)
       CROSS_COMPILE = arm-hisiv200-linux-
endif
MODULE_NAME := rtl8192eu
ifeq ($(KSRC),)
       KSRC := ../../../../../../kernel/linux-3.4.y
endif
endif
# Platform setting
ifeq ($(CONFIG_PLATFORM_ARM_SPREADTRUM_6820), y)
ifeq ($(CONFIG_ANDROID_2X), y)
EXTRA_CFLAGS += -DANDROID_2X
endif
EXTRA_CFLAGS += -DCONFIG_PLATFORM_SPRD
EXTRA_CFLAGS += -DPLATFORM_SPREADTRUM_6820
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ifeq ($(RTL871X), rtl8188e)
EXTRA_CFLAGS += -DSOFTAP_PS_DURATION=50
endif
ifeq ($(CONFIG_SDIO_HCI), y)
EXTRA_CFLAGS += -DCONFIG_PLATFORM_OPS
_PLATFORM_FILES += platform/platform_sprd_sdio.o
endif
endif
ifeq ($(CONFIG_PLATFORM_ARM_SPREADTRUM_8810), y)
ifeq ($(CONFIG_ANDROID_2X), y)
EXTRA_CFLAGS += -DANDROID_2X
endif
EXTRA_CFLAGS += -DCONFIG_PLATFORM_SPRD
EXTRA_CFLAGS += -DPLATFORM_SPREADTRUM_8810
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ifeq ($(RTL871X), rtl8188e)
EXTRA_CFLAGS += -DSOFTAP_PS_DURATION=50
endif
ifeq ($(CONFIG_SDIO_HCI), y)
EXTRA_CFLAGS += -DCONFIG_PLATFORM_OPS
_PLATFORM_FILES += platform/platform_sprd_sdio.o
endif
endif
ifeq ($(CONFIG_PLATFORM_ARM_WMT), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
EXTRA_CFLAGS += -DCONFIG_PLATFORM_OPS
ifeq ($(CONFIG_SDIO_HCI), y)
_PLATFORM_FILES += platform/platform_ARM_WMT_sdio.o
endif
ARCH := arm
CROSS_COMPILE := /home/android_sdk/WonderMedia/wm8880-android4.4/toolchain/arm_201103_gcc4.5.2/mybin/arm_1103_le-
KSRC := /home/android_sdk/WonderMedia/wm8880-android4.4/kernel4.4/
MODULE_NAME :=8189es_kk
endif
ifeq ($(CONFIG_PLATFORM_RTK119X), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
#EXTRA_CFLAGS += -DCONFIG_PLATFORM_ARM_SUN7I
EXTRA_CFLAGS += -DCONFIG_TRAFFIC_PROTECT
# default setting for Android 4.1, 4.2
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IFACE_NUMBER=3
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
#EXTRA_CFLAGS +=  -DCONFIG_QOS_OPTIMIZATION
EXTRA_CFLAGS += -DCONFIG_QOS_OPTIMIZATION
#EXTRA_CFLAGS += -DCONFIG_#PLATFORM_OPS
ifeq ($(CONFIG_USB_HCI), y)
EXTRA_CFLAGS += -DCONFIG_USE_USB_BUFFER_ALLOC_TX
#_PLATFORM_FILES += platform/platform_ARM_SUNxI_usb.o
endif
ifeq ($(CONFIG_SDIO_HCI), y)
_PLATFORM_FILES += platform/platform_ARM_SUNnI_sdio.o
endif
ARCH := arm
# ==== Cross compile setting for Android 4.4 SDK =====
#CROSS_COMPILE := arm-linux-gnueabihf-
KVER  := 3.10.24
#KSRC :=/home/android_sdk/Allwinner/a20/android-kitkat44/lichee/linux-3.4
CROSS_COMPILE := /home/realtek/software_phoenix/phoenix/toolchain/usr/local/arm-2013.11/bin/arm-linux-gnueabihf-
KSRC := /home/realtek/software_phoenix/linux-kernel
MODULE_NAME := 8192eu
endif
ifeq ($(CONFIG_PLATFORM_RTK129X), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DRTK_129X_PLATFORM
EXTRA_CFLAGS += -DCONFIG_TRAFFIC_PROTECT
# default setting for Android 4.1, 4.2
#EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
#EXTRA_CFLAGS += -DCONFIG_P2P_IPS -DCONFIG_QOS_OPTIMIZATION
EXTRA_CFLAGS += -DCONFIG_QOS_OPTIMIZATION
EXTRA_CFLAGS += -Wno-error=date-time
# default setting for Android 7.0
ifeq ($(RTK_ANDROID_VERSION), nougat)
EXTRA_CFLAGS += -DRTW_P2P_GROUP_INTERFACE=1
endif
#EXTRA_CFLAGS += -DCONFIG_#PLATFORM_OPS
ifeq ($(CONFIG_USB_HCI), y)
EXTRA_CFLAGS += -DCONFIG_USE_USB_BUFFER_ALLOC_TX
#_PLATFORM_FILES += platform/platform_ARM_SUNxI_usb.o
endif
ifeq ($(CONFIG_SDIO_HCI), y)
_PLATFORM_FILES += platform/platform_ARM_SUNnI_sdio.o
endif
ARCH := arm64
# ==== Cross compile setting for Android 4.4 SDK =====
#CROSS_COMPILE := arm-linux-gnueabihf-
KVER  := 4.1.10
CROSS_COMPILE := $(CROSS)
KSRC := $(LINUX_KERNEL_PATH)
MODULE_NAME := 8822be
endif
ifeq ($(CONFIG_PLATFORM_NOVATEK_NT72668), y)
EXTRA_CFLAGS += -DCONFIG_PLATFORM_NOVATEK_NT72668
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
EXTRA_CFLAGS += -DCONFIG_USE_USB_BUFFER_ALLOC_RX
EXTRA_CFLAGS += -DCONFIG_USE_USB_BUFFER_ALLOC_TX
ARCH ?= arm
CROSS_COMPILE := arm-linux-gnueabihf-
KVER := 3.8.0
KSRC := /Custom/Novatek/TCL/linux-3.8_header
#KSRC := $(KERNELDIR)
endif
ifeq ($(CONFIG_PLATFORM_ARM_TCC8930_JB42), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
# default setting for Android 4.1, 4.2
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
ARCH := arm
CROSS_COMPILE := /home/android_sdk/Telechips/v13.05_r1-tcc-android-4.2.2_tcc893x-evm_build/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
KSRC := /home/android_sdk/Telechips/v13.05_r1-tcc-android-4.2.2_tcc893x-evm_build/kernel
MODULE_NAME := wlan
endif
ifeq ($(CONFIG_MULTIDRV), y)
ifeq ($(CONFIG_SDIO_HCI), y)
MODULE_NAME := rtw_sdio
endif
ifeq ($(CONFIG_USB_HCI), y)
MODULE_NAME := rtw_usb
endif
ifeq ($(CONFIG_PCI_HCI), y)
MODULE_NAME := rtw_pci
endif
endif
USER_MODULE_NAME ?=
ifneq ($(USER_MODULE_NAME),)
MODULE_NAME := $(USER_MODULE_NAME)
endif
ifneq ($(KERNELRELEASE),)
rtk_core :=    core/rtw_cmd.o \
        core/rtw_security.o \
        core/rtw_debug.o \
        core/rtw_io.o \
        core/rtw_ioctl_query.o \
        core/rtw_ioctl_set.o \
        core/rtw_ieee80211.o \
        core/rtw_mlme.o \
        core/rtw_mlme_ext.o \
        core/rtw_mi.o \
        core/rtw_wlan_util.o \
        core/rtw_vht.o \
        core/rtw_pwrctrl.o \
        core/rtw_rf.o \
        core/rtw_recv.o \
        core/rtw_sta_mgt.o \
        core/rtw_ap.o \
        core/rtw_xmit.o    \
        core/rtw_p2p.o \
        core/rtw_tdls.o \
        core/rtw_br_ext.o \
        core/rtw_iol.o \
        core/rtw_sreset.o \
        core/rtw_btcoex_wifionly.o \
        core/rtw_btcoex.o \
        core/rtw_beamforming.o \
        core/rtw_odm.o \
        core/efuse/rtw_efuse.o
ifeq ($(CONFIG_SDIO_HCI), y)
rtk_core += core/rtw_sdio.o
endif
$(MODULE_NAME)-y += $(rtk_core)
$(MODULE_NAME)-$(CONFIG_INTEL_WIDI) += core/rtw_intel_widi.o
$(MODULE_NAME)-$(CONFIG_WAPI_SUPPORT) += core/rtw_wapi.o    \
                    core/rtw_wapi_sms4.o
$(MODULE_NAME)-y += $(_OS_INTFS_FILES)
$(MODULE_NAME)-y += $(_HAL_INTFS_FILES)
$(MODULE_NAME)-y += $(_OUTSRC_FILES)
$(MODULE_NAME)-y += $(_PLATFORM_FILES)
$(MODULE_NAME)-$(CONFIG_MP_INCLUDED) += core/rtw_mp.o
ifeq ($(CONFIG_RTL8723B), y)
$(MODULE_NAME)-$(CONFIG_MP_INCLUDED)+= core/rtw_bt_mp.o
endif
obj-$(CONFIG_RTL8188EU) := $(MODULE_NAME).o
else
export CONFIG_RTL8188EU = m
all: modules
modules:
    $(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KSRC) M=$(shell pwd)  modules
strip:
    $(CROSS_COMPILE)strip $(MODULE_NAME).ko --strip-unneeded
install:
    install -p -m 644 $(MODULE_NAME).ko  $(MODDESTDIR)
    /sbin/depmod -a ${KVER}
uninstall:
    rm -f $(MODDESTDIR)/$(MODULE_NAME).ko
    /sbin/depmod -a ${KVER}
config_r:
    @echo "make config"
    /bin/bash script/Configure script/config.in
.PHONY: modules clean
clean:
    #$(MAKE) -C $(KSRC) M=$(shell pwd) clean
    cd hal ; rm -fr */*/*/*.mod.c */*/*/*.mod */*/*/*.o */*/*/.*.cmd */*/*/*.ko
    cd hal ; rm -fr */*/*.mod.c */*/*.mod */*/*.o */*/.*.cmd */*/*.ko
    cd hal ; rm -fr */*.mod.c */*.mod */*.o */.*.cmd */*.ko
    cd hal ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko
    cd core/efuse ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko
    cd core ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko
    cd os_dep/linux ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko
    cd os_dep ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko
    cd platform ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko
    rm -fr Module.symvers ; rm -fr Module.markers ; rm -fr modules.order
    rm -fr *.mod.c *.mod *.o .*.cmd *.ko *~
    rm -fr .tmp_versions .cache.mk
endif
linux-bsp/drivers/rtl8188eus/README.md
New file
@@ -0,0 +1,61 @@
# Download
Downlink from https://github.com/quickreflex/rtl8188eus.git, 2019.08.19
# ChangeLog
1, Remove unused files/scripts
2, Update Makefile remove driver debug information "CONFIG_RTW_DEBUG = n"
3, Update Makefile support SAMA5D4 compile
# rtl8188eus
Wifi driver support for rtl8188eu, rtl8188eus and rtl8188etv chips and working under the new linux kernel (5.1.x).
More information about your wifi device can be found here: https://wikidevi.com.
Compiling & Building
---------
### Dependencies
To compile the driver, you need to have make and a compiler installed. In addition,
you must have the kernel headers installed. If you do not understand what this means,
consult your distro. if compile a new kernel, you will need to set two parameters
with make: KSRC=path_to_kernel_source and KVER=kernel_version. The same goes for installation.
### Download
```
git clone -b v5.2.2.4 https://github.com/quickreflex/rtl8188eus.git
cd rtl8188eu
```
### Compiling & Installing
```
make all
make install
```
Or with DKMS
```
dkms add .
dkms build 8188eu/1.0
dkms install 8188eu/1.0
```
Switch modes
---------
### Supported interface modes
```
* IBSS
* managed
* AP
* monitor
* P2P-client
* P2P-GO
```
### For setting interface modes
```
ifconfig wlan0 down
iw dev wlan0 set type managed
ifconfig wlan0 up
```
### For setting TX power
```
iw wlan0 set txpower fixed 1300
```
linux-bsp/drivers/rtl8188eus/core/efuse/rtw_efuse.c
New file
@@ -0,0 +1,2949 @@
/******************************************************************************
 *
 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 *
 ******************************************************************************/
#define _RTW_EFUSE_C_
#include <drv_types.h>
#include <hal_data.h>
#include "../hal/efuse/efuse_mask.h"
/*------------------------Define local variable------------------------------*/
u8    fakeEfuseBank = {0};
u32    fakeEfuseUsedBytes = {0};
u8    fakeEfuseContent[EFUSE_MAX_HW_SIZE] = {0};
u8    fakeEfuseInitMap[EFUSE_MAX_MAP_LEN] = {0};
u8    fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN] = {0};
u32    BTEfuseUsedBytes = {0};
u8    BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
u8    BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
u8    BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
u32    fakeBTEfuseUsedBytes = {0};
u8    fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
u8    fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
u8    fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
u8    maskfileBuffer[64];
/*------------------------Define local variable------------------------------*/
BOOLEAN rtw_file_efuse_IsMasked(PADAPTER pAdapter, u16 Offset)
{
    int r = Offset / 16;
    int c = (Offset % 16) / 2;
    int result = 0;
    if (pAdapter->registrypriv.boffefusemask)
        return FALSE;
    if (c < 4) /* Upper double word */
        result = (maskfileBuffer[r] & (0x10 << c));
    else
        result = (maskfileBuffer[r] & (0x01 << (c - 4)));
    return (result > 0) ? 0 : 1;
}
BOOLEAN efuse_IsMasked(PADAPTER pAdapter, u16 Offset)
{
    PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
    if (pAdapter->registrypriv.boffefusemask)
        return FALSE;
#if DEV_BUS_TYPE == RT_USB_INTERFACE
#if defined(CONFIG_RTL8188E)
    if (IS_HARDWARE_TYPE_8188E(pAdapter))
        return (IS_MASKED(8188E, _MUSB, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8812A)
    if (IS_HARDWARE_TYPE_8812(pAdapter))
        return (IS_MASKED(8812A, _MUSB, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8821A)
#if 0
    if (IS_HARDWARE_TYPE_8811AU(pAdapter))
        return (IS_MASKED(8811A, _MUSB, Offset)) ? TRUE : FALSE;
#endif
    if (IS_HARDWARE_TYPE_8821(pAdapter))
        return (IS_MASKED(8821A, _MUSB, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8192E)
    if (IS_HARDWARE_TYPE_8192E(pAdapter))
        return (IS_MASKED(8192E, _MUSB, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8723B)
    if (IS_HARDWARE_TYPE_8723B(pAdapter))
        return (IS_MASKED(8723B, _MUSB, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8703B)
    if (IS_HARDWARE_TYPE_8703B(pAdapter))
        return (IS_MASKED(8703B, _MUSB, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8814A)
    if (IS_HARDWARE_TYPE_8814A(pAdapter))
        return (IS_MASKED(8814A, _MUSB, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8188F)
    if (IS_HARDWARE_TYPE_8188F(pAdapter))
        return (IS_MASKED(8188F, _MUSB, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8822B)
    if (IS_HARDWARE_TYPE_8822B(pAdapter))
        return (IS_MASKED(8822B, _MUSB, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8723D)
    if (IS_HARDWARE_TYPE_8723D(pAdapter))
        return (IS_MASKED(8723D, _MUSB, Offset)) ? TRUE : FALSE;
#endif
    /*#if defined(CONFIG_RTL8821C)
        if (IS_HARDWARE_TYPE_8821C(pAdapter))
            return (IS_MASKED(8821C,_MUSB,Offset)) ? TRUE : FALSE;
    #endif*/
#elif DEV_BUS_TYPE == RT_PCI_INTERFACE
#if defined(CONFIG_RTL8188E)
    if (IS_HARDWARE_TYPE_8188E(pAdapter))
        return (IS_MASKED(8188E, _MPCIE, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8192E)
    if (IS_HARDWARE_TYPE_8192E(pAdapter))
        return (IS_MASKED(8192E, _MPCIE, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8812A)
    if (IS_HARDWARE_TYPE_8812(pAdapter))
        return (IS_MASKED(8812A, _MPCIE, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8821A)
    if (IS_HARDWARE_TYPE_8821(pAdapter))
        return (IS_MASKED(8821A, _MPCIE, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8723B)
    if (IS_HARDWARE_TYPE_8723B(pAdapter))
        return (IS_MASKED(8723B, _MPCIE, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8814A)
    if (IS_HARDWARE_TYPE_8814A(pAdapter))
        return (IS_MASKED(8814A, _MPCIE, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8822B)
    if (IS_HARDWARE_TYPE_8822B(pAdapter))
        return (IS_MASKED(8822B, _MPCIE, Offset)) ? TRUE : FALSE;
#endif
#elif DEV_BUS_TYPE == RT_SDIO_INTERFACE
#ifdef CONFIG_RTL8188E_SDIO
    if (IS_HARDWARE_TYPE_8188E(pAdapter))
        return (IS_MASKED(8188E, _MSDIO, Offset)) ? TRUE : FALSE;
#endif
#ifdef CONFIG_RTL8188F_SDIO
    if (IS_HARDWARE_TYPE_8188F(pAdapter))
        return (IS_MASKED(8188F, _MSDIO, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8821C)
    if (IS_HARDWARE_TYPE_8821C(pAdapter))
        return (IS_MASKED(8821C, _MSDIO, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8822B)
    if (IS_HARDWARE_TYPE_8822B(pAdapter))
        return (IS_MASKED(8822B, _MSDIO, Offset)) ? TRUE : FALSE;
#endif
#endif
    return FALSE;
}
void rtw_efuse_mask_array(PADAPTER pAdapter, u8 *pArray)
{
    PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
#if DEV_BUS_TYPE == RT_USB_INTERFACE
#if defined(CONFIG_RTL8188E)
    if (IS_HARDWARE_TYPE_8188E(pAdapter))
        GET_MASK_ARRAY(8188E, _MUSB, pArray);
#endif
#if defined(CONFIG_RTL8812A)
    if (IS_HARDWARE_TYPE_8812(pAdapter))
        GET_MASK_ARRAY(8812A, _MUSB, pArray);
#endif
#if defined(CONFIG_RTL8821A)
    if (IS_HARDWARE_TYPE_8821(pAdapter))
        GET_MASK_ARRAY(8821A, _MUSB, pArray);
#endif
#if defined(CONFIG_RTL8192E)
    if (IS_HARDWARE_TYPE_8192E(pAdapter))
        GET_MASK_ARRAY(8192E, _MUSB, pArray);
#endif
#if defined(CONFIG_RTL8723B)
    if (IS_HARDWARE_TYPE_8723B(pAdapter))
        GET_MASK_ARRAY(8723B, _MUSB, pArray);
#endif
#if defined(CONFIG_RTL8703B)
    if (IS_HARDWARE_TYPE_8703B(pAdapter))
        GET_MASK_ARRAY(8703B, _MUSB, pArray);
#endif
#if defined(CONFIG_RTL8188F)
    if (IS_HARDWARE_TYPE_8188F(pAdapter))
        GET_MASK_ARRAY(8188F, _MUSB, pArray);
#endif
#if defined(CONFIG_RTL8814A)
    if (IS_HARDWARE_TYPE_8814A(pAdapter))
        GET_MASK_ARRAY(8814A, _MUSB, pArray);
#endif
#if defined(CONFIG_RTL8822B)
    if (IS_HARDWARE_TYPE_8822B(pAdapter))
        GET_MASK_ARRAY(8822B, _MUSB, pArray);
#endif
    /*#if defined(CONFIG_RTL8821C)
        if (IS_HARDWARE_TYPE_8821C(pAdapter))
            GET_MASK_ARRAY(8821C,_MUSB,pArray);
    #endif*/
#elif DEV_BUS_TYPE == RT_PCI_INTERFACE
#if defined(CONFIG_RTL8188E)
    if (IS_HARDWARE_TYPE_8188E(pAdapter))
        GET_MASK_ARRAY(8188E, _MPCIE, pArray);
#endif
#if defined(CONFIG_RTL8192E)
    if (IS_HARDWARE_TYPE_8192E(pAdapter))
        GET_MASK_ARRAY(8192E, _MPCIE, pArray);
#endif
#if defined(CONFIG_RTL8812A)
    if (IS_HARDWARE_TYPE_8812(pAdapter))
        GET_MASK_ARRAY(8812A, _MPCIE, pArray);
#endif
#if defined(CONFIG_RTL8821A)
    if (IS_HARDWARE_TYPE_8821(pAdapter))
        GET_MASK_ARRAY(8821A, _MPCIE, pArray);
#endif
#if defined(CONFIG_RTL8723B)
    if (IS_HARDWARE_TYPE_8723B(pAdapter))
        GET_MASK_ARRAY(8723B, _MPCIE, pArray);
#endif
#if defined(CONFIG_RTL8814A)
    if (IS_HARDWARE_TYPE_8814A(pAdapter))
        GET_MASK_ARRAY(8814A, _MPCIE, pArray);
#endif
#if defined(CONFIG_RTL8822B)
    if (IS_HARDWARE_TYPE_8822B(pAdapter))
        GET_MASK_ARRAY(8822B, _MPCIE, pArray);
#endif
#elif DEV_BUS_TYPE == RT_SDIO_INTERFACE
#if defined(CONFIG_RTL8188E)
    if (IS_HARDWARE_TYPE_8188E(pAdapter))
        GET_MASK_ARRAY(8188E, _MSDIO, pArray);
#endif
#if defined(CONFIG_RTL8188F)
    if (IS_HARDWARE_TYPE_8188F(pAdapter))
        GET_MASK_ARRAY(8188F, _MSDIO, pArray);
#endif
#if defined(CONFIG_RTL8821C)
    if (IS_HARDWARE_TYPE_8821C(pAdapter))
        GET_MASK_ARRAY(8821C , _MSDIO, pArray);
#endif
#if defined(CONFIG_RTL8822B)
    if (IS_HARDWARE_TYPE_8822B(pAdapter))
        GET_MASK_ARRAY(8822B , _MSDIO, pArray);
#endif
#endif /*#elif DEV_BUS_TYPE == RT_SDIO_INTERFACE*/
}
u16 rtw_get_efuse_mask_arraylen(PADAPTER pAdapter)
{
    HAL_DATA_TYPE    *pHalData = GET_HAL_DATA(pAdapter);
#if DEV_BUS_TYPE == RT_USB_INTERFACE
#if defined(CONFIG_RTL8188E)
    if (IS_HARDWARE_TYPE_8188E(pAdapter))
        return GET_MASK_ARRAY_LEN(8188E, _MUSB);
#endif
#if defined(CONFIG_RTL8812A)
    if (IS_HARDWARE_TYPE_8812(pAdapter))
        return GET_MASK_ARRAY_LEN(8812A, _MUSB);
#endif
#if defined(CONFIG_RTL8821A)
    if (IS_HARDWARE_TYPE_8821(pAdapter))
        return GET_MASK_ARRAY_LEN(8821A, _MUSB);
#endif
#if defined(CONFIG_RTL8192E)
    if (IS_HARDWARE_TYPE_8192E(pAdapter))
        return GET_MASK_ARRAY_LEN(8192E, _MUSB);
#endif
#if defined(CONFIG_RTL8723B)
    if (IS_HARDWARE_TYPE_8723B(pAdapter))
        return GET_MASK_ARRAY_LEN(8723B, _MUSB);
#endif
#if defined(CONFIG_RTL8703B)
    if (IS_HARDWARE_TYPE_8703B(pAdapter))
        return GET_MASK_ARRAY_LEN(8703B, _MUSB);
#endif
#if defined(CONFIG_RTL8188F)
    if (IS_HARDWARE_TYPE_8188F(pAdapter))
        return GET_MASK_ARRAY_LEN(8188F, _MUSB);
#endif
#if defined(CONFIG_RTL8814A)
    if (IS_HARDWARE_TYPE_8814A(pAdapter))
        return GET_MASK_ARRAY_LEN(8814A, _MUSB);
#endif
#if defined(CONFIG_RTL8822B)
    if (IS_HARDWARE_TYPE_8822B(pAdapter))
        return GET_MASK_ARRAY_LEN(8822B, _MUSB);
#endif
    /*#if defined(CONFIG_RTL8821C)
        if (IS_HARDWARE_TYPE_8821C(pAdapter))
            return GET_MASK_ARRAY_LEN(8821C,_MUSB);
    #endif*/
#elif DEV_BUS_TYPE == RT_PCI_INTERFACE
#if defined(CONFIG_RTL8188E)
    if (IS_HARDWARE_TYPE_8188E(pAdapter))
        return GET_MASK_ARRAY_LEN(8188E, _MPCIE);
#endif
#if defined(CONFIG_RTL8192E)
    if (IS_HARDWARE_TYPE_8192E(pAdapter))
        return GET_MASK_ARRAY_LEN(8192E, _MPCIE);
#endif
#if defined(CONFIG_RTL8812A)
    if (IS_HARDWARE_TYPE_8812(pAdapter))
        return GET_MASK_ARRAY_LEN(8812A, _MPCIE);
#endif
#if defined(CONFIG_RTL8821A)
    if (IS_HARDWARE_TYPE_8821(pAdapter))
        return GET_MASK_ARRAY_LEN(8821A, _MPCIE);
#endif
#if defined(CONFIG_RTL8723B)
    if (IS_HARDWARE_TYPE_8723B(pAdapter))
        return GET_MASK_ARRAY_LEN(8723B, _MPCIE);
#endif
#if defined(CONFIG_RTL8814A)
    if (IS_HARDWARE_TYPE_8814A(pAdapter))
        return GET_MASK_ARRAY_LEN(8814A, _MPCIE);
#endif
#if defined(CONFIG_RTL8822B)
    if (IS_HARDWARE_TYPE_8822B(pAdapter))
        return GET_MASK_ARRAY_LEN(8822B, _MPCIE);
#endif
#elif DEV_BUS_TYPE == RT_SDIO_INTERFACE
#if defined(CONFIG_RTL8188E)
    if (IS_HARDWARE_TYPE_8188E(pAdapter))
        return GET_MASK_ARRAY_LEN(8188E, _MSDIO);
#endif
#if defined(CONFIG_RTL8188F)
    if (IS_HARDWARE_TYPE_8188F(pAdapter))
        return GET_MASK_ARRAY_LEN(8188F, _MSDIO);
#endif
#if defined(CONFIG_RTL8821C)
    if (IS_HARDWARE_TYPE_8821C(pAdapter))
        return GET_MASK_ARRAY_LEN(8821C, _MSDIO);
#endif
#if defined(CONFIG_RTL8822B)
    if (IS_HARDWARE_TYPE_8822B(pAdapter))
        return GET_MASK_ARRAY_LEN(8822B, _MSDIO);
#endif
#endif
    return 0;
}
u8 rtw_efuse_mask_map_read(PADAPTER padapter, u16 addr, u16 cnts, u8 *data)
{
    u8    ret = _SUCCESS;
    u16    mapLen = 0, i = 0;
    EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, _FALSE);
    ret = rtw_efuse_map_read(padapter, addr, cnts , data);
    if (padapter->registrypriv.boffefusemask == 0) {
        for (i = 0; i < cnts; i++) {
            if (padapter->registrypriv.bFileMaskEfuse == _TRUE) {
                if (rtw_file_efuse_IsMasked(padapter, addr + i)) /*use file efuse mask.*/
                    data[i] = 0xff;
            } else {
                /*RTW_INFO(" %s , data[%d] = %x\n", __func__, i, data[i]);*/
                if (efuse_IsMasked(padapter, addr + i)) {
                    data[i] = 0xff;
                    /*RTW_INFO(" %s ,mask data[%d] = %x\n", __func__, i, data[i]);*/
                }
            }
        }
    }
    return ret;
}
#ifdef RTW_HALMAC
#include "../../hal/hal_halmac.h"
void Efuse_PowerSwitch(PADAPTER adapter, u8 write, u8 pwrstate)
{
}
void BTEfuse_PowerSwitch(PADAPTER adapter, u8 write, u8 pwrstate)
{
}
u8 efuse_GetCurrentSize(PADAPTER adapter, u16 *size)
{
    *size = 0;
    return _FAIL;
}
u16 efuse_GetMaxSize(PADAPTER adapter)
{
    struct dvobj_priv *d;
    u32 size = 0;
    int err;
    d = adapter_to_dvobj(adapter);
    err = rtw_halmac_get_physical_efuse_size(d, &size);
    if (err)
        return 0;
    return size;
}
u16 efuse_GetavailableSize(PADAPTER adapter)
{
    struct dvobj_priv *d;
    u32 size = 0;
    int err;
    d = adapter_to_dvobj(adapter);
    err = rtw_halmac_get_available_efuse_size(d, &size);
    if (err)
        return 0;
    return size;
}
u8 efuse_bt_GetCurrentSize(PADAPTER adapter, u16 *usesize)
{
    u8 *efuse_map;
    *usesize = 0;
    efuse_map = rtw_malloc(EFUSE_BT_MAP_LEN);
    if (efuse_map == NULL) {
        RTW_DBG("%s: malloc FAIL\n", __FUNCTION__);
        return _FAIL;
    }
    /* for get bt phy efuse last use byte */
    hal_ReadEFuse_BT_logic_map(adapter, 0x00, EFUSE_BT_MAP_LEN, efuse_map);
    *usesize = fakeBTEfuseUsedBytes;
    if (efuse_map)
        rtw_mfree(efuse_map, EFUSE_BT_MAP_LEN);
    return _SUCCESS;
}
u16 efuse_bt_GetMaxSize(PADAPTER adapter)
{
    return EFUSE_BT_REAL_CONTENT_LEN;
}
void EFUSE_GetEfuseDefinition(PADAPTER adapter, u8 efusetype, u8 type, void *out, BOOLEAN test)
{
    struct dvobj_priv *d;
    u32 v32 = 0;
    d = adapter_to_dvobj(adapter);
    if (adapter->hal_func.EFUSEGetEfuseDefinition) {
        adapter->hal_func.EFUSEGetEfuseDefinition(adapter, efusetype, type, out, test);
        return;
    }
    if (EFUSE_WIFI == efusetype) {
        switch (type) {
        case TYPE_EFUSE_MAP_LEN:
            rtw_halmac_get_logical_efuse_size(d, &v32);
            *(u16 *)out = (u16)v32;
            return;
        case TYPE_EFUSE_REAL_CONTENT_LEN:
            rtw_halmac_get_physical_efuse_size(d, &v32);
            *(u16 *)out = (u16)v32;
            return;
        }
    } else if (EFUSE_BT == efusetype) {
        switch (type) {
        case TYPE_EFUSE_MAP_LEN:
            *(u16 *)out = EFUSE_BT_MAP_LEN;
            return;
        case TYPE_EFUSE_REAL_CONTENT_LEN:
            *(u16 *)out = EFUSE_BT_REAL_CONTENT_LEN;
            return;
        }
    }
}
/*
 * read/write raw efuse data
 */
u8 rtw_efuse_access(PADAPTER adapter, u8 write, u16 addr, u16 cnts, u8 *data)
{
    struct dvobj_priv *d;
    u8 *efuse = NULL;
    u32 size, i;
    int err;
    d = adapter_to_dvobj(adapter);
    err = rtw_halmac_get_physical_efuse_size(d, &size);
    if (err)
        size = EFUSE_MAX_SIZE;
    if ((addr + cnts) > size)
        return _FAIL;
    if (_TRUE == write) {
        err = rtw_halmac_write_physical_efuse(d, addr, cnts, data);
        if (err)
            return _FAIL;
    } else {
        if (cnts > 16)
            efuse = rtw_zmalloc(size);
        if (efuse) {
            err = rtw_halmac_read_physical_efuse_map(d, efuse, size);
            if (err) {
                rtw_mfree(efuse, size);
                return _FAIL;
            }
            _rtw_memcpy(data, efuse + addr, cnts);
            rtw_mfree(efuse, size);
        } else {
            err = rtw_halmac_read_physical_efuse(d, addr, cnts, data);
            if (err)
                return _FAIL;
        }
    }
    return _SUCCESS;
}
static inline void dump_buf(u8 *buf, u32 len)
{
    u32 i;
    RTW_INFO("-----------------Len %d----------------\n", len);
    for (i = 0; i < len; i++)
        printk("%2.2x-", *(buf + i));
    printk("\n");
}
/*
 * read/write raw efuse data
 */
u8 rtw_efuse_bt_access(PADAPTER adapter, u8 write, u16 addr, u16 cnts, u8 *data)
{
    struct dvobj_priv *d;
    u8 *efuse = NULL;
    u32 size, i;
    int err = _FAIL;
    d = adapter_to_dvobj(adapter);
    size = EFUSE_BT_REAL_CONTENT_LEN;
    if ((addr + cnts) > size)
        return _FAIL;
    if (_TRUE == write) {
        err = rtw_halmac_write_bt_physical_efuse(d, addr, cnts, data);
        if (err == -1) {
            RTW_ERR("%s: rtw_halmac_write_bt_physical_efuse fail!\n", __FUNCTION__);
            return _FAIL;
        }
        RTW_INFO("%s: rtw_halmac_write_bt_physical_efuse OK! data 0x%x\n", __FUNCTION__, *data);
    } else {
        efuse = rtw_zmalloc(size);
        if (efuse) {
            err = rtw_halmac_read_bt_physical_efuse_map(d, efuse, size);
            if (err == -1) {
                RTW_ERR("%s: rtw_halmac_read_bt_physical_efuse_map fail!\n", __FUNCTION__);
                rtw_mfree(efuse, size);
                return _FAIL;
            }
            dump_buf(efuse + addr, cnts);
            _rtw_memcpy(data, efuse + addr, cnts);
            RTW_INFO("%s: rtw_halmac_read_bt_physical_efuse_map ok! data 0x%x\n", __FUNCTION__, *data);
            rtw_mfree(efuse, size);
        }
    }
    return _SUCCESS;
}
u8 rtw_efuse_map_read(PADAPTER adapter, u16 addr, u16 cnts, u8 *data)
{
    struct dvobj_priv *d;
    u8 *efuse = NULL;
    u32 size, i;
    int err;
    d = adapter_to_dvobj(adapter);
    err = rtw_halmac_get_logical_efuse_size(d, &size);
    if (err)
        return _FAIL;
    /* size error handle */
    if ((addr + cnts) > size) {
        if (addr < size)
            cnts = size - addr;
        else
            return _FAIL;
    }
    if (cnts > 16)
        efuse = rtw_zmalloc(size);
    if (efuse) {
        err = rtw_halmac_read_logical_efuse_map(d, efuse, size);
        if (err) {
            rtw_mfree(efuse, size);
            return _FAIL;
        }
        _rtw_memcpy(data, efuse + addr, cnts);
        rtw_mfree(efuse, size);
    } else {
        err = rtw_halmac_read_logical_efuse(d, addr, cnts, data);
        if (err)
            return _FAIL;
    }
    return _SUCCESS;
}
u8 rtw_efuse_map_write(PADAPTER adapter, u16 addr, u16 cnts, u8 *data)
{
    struct dvobj_priv *d;
    u8 *efuse = NULL;
    u32 size, i;
    int err;
    u8 mask_buf[64] = "";
    u16 mask_len = sizeof(u8) * rtw_get_efuse_mask_arraylen(adapter);
    d = adapter_to_dvobj(adapter);
    err = rtw_halmac_get_logical_efuse_size(d, &size);
    if (err)
        return _FAIL;
    if ((addr + cnts) > size)
        return _FAIL;
    efuse = rtw_zmalloc(size);
    if (!efuse)
        return _FAIL;
    err = rtw_halmac_read_logical_efuse_map(d, efuse, size);
    if (err) {
        rtw_mfree(efuse, size);
        return _FAIL;
    }
    _rtw_memcpy(efuse + addr, data, cnts);
    if (adapter->registrypriv.boffefusemask == 0) {
        RTW_INFO("Use mask Array Len: %d\n", mask_len);
        if (mask_len != 0) {
            if (adapter->registrypriv.bFileMaskEfuse == _TRUE)
                _rtw_memcpy(mask_buf, maskfileBuffer, mask_len);
            else
                rtw_efuse_mask_array(adapter, mask_buf);
            err = rtw_halmac_write_logical_efuse_map(d, efuse, size, mask_buf, mask_len);
        } else
            err = rtw_halmac_write_logical_efuse_map(d, efuse, size, NULL, 0);
    } else {
        _rtw_memset(mask_buf, 0xFF, sizeof(mask_buf));
        RTW_INFO("Efuse mask off\n");
        err = rtw_halmac_write_logical_efuse_map(d, efuse, size, mask_buf, size/16);
    }
    if (err) {
        rtw_mfree(efuse, size);
        return _FAIL;
    }
    rtw_mfree(efuse, size);
    return _SUCCESS;
}
int Efuse_PgPacketRead(PADAPTER adapter, u8 offset, u8 *data, BOOLEAN test)
{
    return _FALSE;
}
int Efuse_PgPacketWrite(PADAPTER adapter, u8 offset, u8 word_en, u8 *data, BOOLEAN test)
{
    return _FALSE;
}
u8 rtw_BT_efuse_map_read(PADAPTER adapter, u16 addr, u16 cnts, u8 *data)
{
    hal_ReadEFuse_BT_logic_map(adapter,addr, cnts, data);
    return _SUCCESS;
}
u8 rtw_BT_efuse_map_write(PADAPTER adapter, u16 addr, u16 cnts, u8 *data)
{
#define RT_ASSERT_RET(expr)                                    \
    if (!(expr)) {                                        \
        printk("Assertion failed! %s at ......\n", #expr);                \
        printk("      ......%s,%s, line=%d\n",__FILE__, __FUNCTION__, __LINE__);    \
        return _FAIL;    \
    }
    u8    offset, word_en;
    u8    *map;
    u8    newdata[PGPKT_DATA_SIZE];
    s32 i = 0, j = 0, idx;
    u8    ret = _SUCCESS;
    u16 mapLen = 1024;
    if ((addr + cnts) > mapLen)
        return _FAIL;
    RT_ASSERT_RET(PGPKT_DATA_SIZE == 8); /* have to be 8 byte alignment */
    RT_ASSERT_RET((mapLen & 0x7) == 0); /* have to be PGPKT_DATA_SIZE alignment for memcpy */
    map = rtw_zmalloc(mapLen);
    if (map == NULL)
        return _FAIL;
    ret = rtw_BT_efuse_map_read(adapter, 0, mapLen, map);
    if (ret == _FAIL)
        goto exit;
    RTW_INFO("OFFSET\tVALUE(hex)\n");
    for (i = 0; i < mapLen; i += 16) { /* set 512 because the iwpriv's extra size have limit 0x7FF */
        RTW_INFO("0x%03x\t", i);
        for (j = 0; j < 8; j++)
            RTW_INFO("%02X ", map[i + j]);
        RTW_INFO("\t");
        for (; j < 16; j++)
            RTW_INFO("%02X ", map[i + j]);
        RTW_INFO("\n");
    }
    RTW_INFO("\n");
    idx = 0;
    offset = (addr >> 3);
    while (idx < cnts) {
        word_en = 0xF;
        j = (addr + idx) & 0x7;
        _rtw_memcpy(newdata, &map[offset << 3], PGPKT_DATA_SIZE);
        for (i = j; i < PGPKT_DATA_SIZE && idx < cnts; i++, idx++) {
            if (data[idx] != map[addr + idx]) {
                word_en &= ~BIT(i >> 1);
                newdata[i] = data[idx];
            }
        }
        if (word_en != 0xF) {
            ret = EfusePgPacketWrite_BT(adapter, offset, word_en, newdata, _FALSE);
            RTW_INFO("offset=%x\n", offset);
            RTW_INFO("word_en=%x\n", word_en);
            RTW_INFO("%s: data=", __FUNCTION__);
            for (i = 0; i < PGPKT_DATA_SIZE; i++)
                RTW_INFO("0x%02X ", newdata[i]);
            RTW_INFO("\n");
            if (ret == _FAIL)
                break;
        }
        offset++;
    }
exit:
    rtw_mfree(map, mapLen);
    return _SUCCESS;
}
VOID hal_ReadEFuse_BT_logic_map(
    PADAPTER    padapter,
    u16            _offset,
    u16            _size_byte,
    u8            *pbuf
)
{
    PHAL_DATA_TYPE    pHalData = GET_HAL_DATA(padapter);
    PEFUSE_HAL        pEfuseHal = &pHalData->EfuseHal;
    u8    *efuseTbl, *phyefuse;
    u8    bank;
    u16    eFuse_Addr = 0;
    u8    efuseHeader, efuseExtHdr, efuseData;
    u8    offset, wden;
    u16    i, total, used;
    u8    efuse_usage;
    /* */
    /* Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. */
    /* */
    if ((_offset + _size_byte) > EFUSE_BT_MAP_LEN) {
        RTW_INFO("%s: Invalid offset(%#x) with read bytes(%#x)!!\n", __FUNCTION__, _offset, _size_byte);
        return;
    }
    efuseTbl = rtw_malloc(EFUSE_BT_MAP_LEN);
    phyefuse = rtw_malloc(EFUSE_BT_REAL_CONTENT_LEN);
    if (efuseTbl == NULL || phyefuse == NULL) {
        RTW_INFO("%s: efuseTbl or phyefuse malloc fail!\n", __FUNCTION__);
        goto exit;
    }
    /* 0xff will be efuse default value instead of 0x00. */
    _rtw_memset(efuseTbl, 0xFF, EFUSE_BT_MAP_LEN);
    _rtw_memset(phyefuse, 0xFF, EFUSE_BT_REAL_CONTENT_LEN);
    if (rtw_efuse_bt_access(padapter, _FALSE, 0, EFUSE_BT_REAL_CONTENT_LEN, phyefuse))
        dump_buf(phyefuse, EFUSE_BT_REAL_BANK_CONTENT_LEN);
    total = BANK_NUM;
    for (bank = 1; bank <= total; bank++) { /* 8723d Max bake 0~2 */
        eFuse_Addr = 0;
        while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
            /* ReadEFuseByte(padapter, eFuse_Addr++, &efuseHeader, bPseudoTest); */
            efuseHeader = phyefuse[eFuse_Addr++];
            if (efuseHeader == 0xFF)
                break;
            RTW_INFO("%s: efuse[%#X]=0x%02x (header)\n", __FUNCTION__, (((bank - 1) * EFUSE_BT_REAL_CONTENT_LEN) + eFuse_Addr - 1), efuseHeader);
            /* Check PG header for section num. */
            if (EXT_HEADER(efuseHeader)) {    /* extended header */
                offset = GET_HDR_OFFSET_2_0(efuseHeader);
                RTW_INFO("%s: extended header offset_2_0=0x%X\n", __FUNCTION__, offset);
                /* ReadEFuseByte(padapter, eFuse_Addr++, &efuseExtHdr, bPseudoTest); */
                efuseExtHdr = phyefuse[eFuse_Addr++];
                RTW_INFO("%s: efuse[%#X]=0x%02x (ext header)\n", __FUNCTION__, (((bank - 1) * EFUSE_BT_REAL_CONTENT_LEN) + eFuse_Addr - 1), efuseExtHdr);
                if (ALL_WORDS_DISABLED(efuseExtHdr))
                    continue;
                offset |= ((efuseExtHdr & 0xF0) >> 1);
                wden = (efuseExtHdr & 0x0F);
            } else {
                offset = ((efuseHeader >> 4) & 0x0f);
                wden = (efuseHeader & 0x0f);
            }
            if (offset < EFUSE_BT_MAX_SECTION) {
                u16 addr;
                /* Get word enable value from PG header */
                RTW_INFO("%s: Offset=%d Worden=%#X\n", __FUNCTION__, offset, wden);
                addr = offset * PGPKT_DATA_SIZE;
                for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
                    /* Check word enable condition in the section */
                    if (!(wden & (0x01 << i))) {
                        efuseData = 0;
                        /* ReadEFuseByte(padapter, eFuse_Addr++, &efuseData, bPseudoTest); */
                        efuseData = phyefuse[eFuse_Addr++];
                        RTW_INFO("%s: efuse[%#X]=0x%02X\n", __FUNCTION__, eFuse_Addr - 1, efuseData);
                        efuseTbl[addr] = efuseData;
                        efuseData = 0;
                        /* ReadEFuseByte(padapter, eFuse_Addr++, &efuseData, bPseudoTest); */
                        efuseData = phyefuse[eFuse_Addr++];
                        RTW_INFO("%s: efuse[%#X]=0x%02X\n", __FUNCTION__, eFuse_Addr - 1, efuseData);
                        efuseTbl[addr + 1] = efuseData;
                    }
                    addr += 2;
                }
            } else {
                RTW_INFO("%s: offset(%d) is illegal!!\n", __FUNCTION__, offset);
                eFuse_Addr += Efuse_CalculateWordCnts(wden) * 2;
            }
        }
        if ((eFuse_Addr - 1) < total) {
            RTW_INFO("%s: bank(%d) data end at %#x\n", __FUNCTION__, bank, eFuse_Addr - 1);
            break;
        }
    }
    /* switch bank back to bank 0 for later BT and wifi use. */
    //hal_EfuseSwitchToBank(padapter, 0, bPseudoTest);
    /* Copy from Efuse map to output pointer memory!!! */
    for (i = 0; i < _size_byte; i++)
        pbuf[i] = efuseTbl[_offset + i];
    /* Calculate Efuse utilization */
    total = EFUSE_BT_REAL_BANK_CONTENT_LEN;
    used = eFuse_Addr - 1;
    if (total)
        efuse_usage = (u8)((used * 100) / total);
    else
        efuse_usage = 100;
    fakeBTEfuseUsedBytes = used;
    RTW_INFO("%s: BTEfuseUsed last Bytes = %#x\n", __FUNCTION__, fakeBTEfuseUsedBytes);
exit:
    if (efuseTbl)
        rtw_mfree(efuseTbl, EFUSE_BT_MAP_LEN);
    if (phyefuse)
        rtw_mfree(phyefuse, EFUSE_BT_REAL_BANK_CONTENT_LEN);
}
static u8 hal_EfusePartialWriteCheck(
    PADAPTER        padapter,
    u8                efuseType,
    u16                *pAddr,
    PPGPKT_STRUCT    pTargetPkt,
    u8                bPseudoTest)
{
    PHAL_DATA_TYPE    pHalData = GET_HAL_DATA(padapter);
    PEFUSE_HAL        pEfuseHal = &pHalData->EfuseHal;
    u8    bRet = _FALSE;
    u16    startAddr = 0, efuse_max_available_len = EFUSE_BT_REAL_BANK_CONTENT_LEN, efuse_max = EFUSE_BT_REAL_BANK_CONTENT_LEN;
    u8    efuse_data = 0;
    startAddr = (u16)fakeBTEfuseUsedBytes;
    startAddr %= efuse_max;
    RTW_INFO("%s: startAddr=%#X\n", __FUNCTION__, startAddr);
    while (1) {
        if (startAddr >= efuse_max_available_len) {
            bRet = _FALSE;
            RTW_INFO("%s: startAddr(%d) >= efuse_max_available_len(%d)\n",
                __FUNCTION__, startAddr, efuse_max_available_len);
            break;
        }
        if (rtw_efuse_bt_access(padapter, _FALSE, startAddr, 1, &efuse_data)&& (efuse_data != 0xFF)) {
            bRet = _FALSE;
            RTW_INFO("%s: Something Wrong! last bytes(%#X=0x%02X) is not 0xFF\n",
                 __FUNCTION__, startAddr, efuse_data);
            break;
        } else {
            /* not used header, 0xff */
            *pAddr = startAddr;
            /*            RTW_INFO("%s: Started from unused header offset=%d\n", __FUNCTION__, startAddr)); */
            bRet = _TRUE;
            break;
        }
    }
    return bRet;
}
static u8 hal_EfusePgPacketWrite2ByteHeader(
    PADAPTER        padapter,
    u8                efuseType,
    u16                *pAddr,
    PPGPKT_STRUCT    pTargetPkt,
    u8                bPseudoTest)
{
    u16    efuse_addr, efuse_max_available_len = EFUSE_BT_REAL_BANK_CONTENT_LEN;
    u8    pg_header = 0, tmp_header = 0;
    u8    repeatcnt = 0;
    /*    RTW_INFO("%s\n", __FUNCTION__); */
    efuse_addr = *pAddr;
    if (efuse_addr >= efuse_max_available_len) {
        RTW_INFO("%s: addr(%d) over avaliable(%d)!!\n", __FUNCTION__, efuse_addr, efuse_max_available_len);
        return _FALSE;
    }
    pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
    /*    RTW_INFO("%s: pg_header=0x%x\n", __FUNCTION__, pg_header); */
    do {
        rtw_efuse_bt_access(padapter, _TRUE, efuse_addr, 1, &pg_header);
        rtw_efuse_bt_access(padapter, _FALSE, efuse_addr, 1, &tmp_header);
        if (tmp_header != 0xFF)
            break;
        if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
            RTW_INFO("%s: Repeat over limit for pg_header!!\n", __FUNCTION__);
            return _FALSE;
        }
    } while (1);
    if (tmp_header != pg_header) {
        RTW_ERR("%s: PG Header Fail!!(pg=0x%02X read=0x%02X)\n", __FUNCTION__, pg_header, tmp_header);
        return _FALSE;
    }
    /* to write ext_header */
    efuse_addr++;
    pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
    do {
        rtw_efuse_bt_access(padapter, _TRUE, efuse_addr, 1, &pg_header);
        rtw_efuse_bt_access(padapter, _FALSE, efuse_addr, 1, &tmp_header);
        if (tmp_header != 0xFF)
            break;
        if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
            RTW_INFO("%s: Repeat over limit for ext_header!!\n", __FUNCTION__);
            return _FALSE;
        }
    } while (1);
    if (tmp_header != pg_header) {    /* offset PG fail */
        RTW_ERR("%s: PG EXT Header Fail!!(pg=0x%02X read=0x%02X)\n", __FUNCTION__, pg_header, tmp_header);
        return _FALSE;
    }
    *pAddr = efuse_addr;
    return _TRUE;
}
static u8 hal_EfusePgPacketWrite1ByteHeader(
    PADAPTER        pAdapter,
    u8                efuseType,
    u16                *pAddr,
    PPGPKT_STRUCT    pTargetPkt,
    u8                bPseudoTest)
{
    u8    bRet = _FALSE;
    u8    pg_header = 0, tmp_header = 0;
    u16    efuse_addr = *pAddr;
    u8    repeatcnt = 0;
    /*    RTW_INFO("%s\n", __FUNCTION__); */
    pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
    do {
        rtw_efuse_bt_access(pAdapter, _TRUE, efuse_addr, 1, &pg_header);
        rtw_efuse_bt_access(pAdapter, _FALSE, efuse_addr, 1, &tmp_header);
        if (tmp_header != 0xFF)
            break;
        if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
            RTW_INFO("%s: Repeat over limit for pg_header!!\n", __FUNCTION__);
            return _FALSE;
        }
    } while (1);
    if (tmp_header != pg_header) {
        RTW_ERR("%s: PG Header Fail!!(pg=0x%02X read=0x%02X)\n", __FUNCTION__, pg_header, tmp_header);
        return _FALSE;
    }
    *pAddr = efuse_addr;
    return _TRUE;
}
static u8 hal_EfusePgPacketWriteHeader(
    PADAPTER        padapter,
    u8                efuseType,
    u16                *pAddr,
    PPGPKT_STRUCT    pTargetPkt,
    u8                bPseudoTest)
{
    u8 bRet = _FALSE;
    if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
        bRet = hal_EfusePgPacketWrite2ByteHeader(padapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
    else
        bRet = hal_EfusePgPacketWrite1ByteHeader(padapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
    return bRet;
}
static u8
Hal_EfuseWordEnableDataWrite(
    PADAPTER    padapter,
    u16            efuse_addr,
    u8            word_en,
    u8            *data,
    u8            bPseudoTest)
{
    u16    tmpaddr = 0;
    u16    start_addr = efuse_addr;
    u8    badworden = 0x0F;
    u8    tmpdata[PGPKT_DATA_SIZE];
    /*    RTW_INFO("%s: efuse_addr=%#x word_en=%#x\n", __FUNCTION__, efuse_addr, word_en); */
    _rtw_memset(tmpdata, 0xFF, PGPKT_DATA_SIZE);
    if (!(word_en & BIT(0))) {
        tmpaddr = start_addr;
        rtw_efuse_bt_access(padapter, _TRUE, start_addr++, 1, &data[0]);
        rtw_efuse_bt_access(padapter, _TRUE, start_addr++, 1, &data[1]);
        rtw_efuse_bt_access(padapter, _FALSE, tmpaddr, 1, &tmpdata[0]);
        rtw_efuse_bt_access(padapter, _FALSE, tmpaddr + 1, 1, &tmpdata[1]);
        if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
            badworden &= (~BIT(0));
    }
    if (!(word_en & BIT(1))) {
        tmpaddr = start_addr;
        rtw_efuse_bt_access(padapter, _TRUE, start_addr++, 1, &data[2]);
        rtw_efuse_bt_access(padapter, _TRUE, start_addr++, 1, &data[3]);
        rtw_efuse_bt_access(padapter, _FALSE, tmpaddr, 1, &tmpdata[2]);
        rtw_efuse_bt_access(padapter, _FALSE, tmpaddr + 1, 1, &tmpdata[3]);
        if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
            badworden &= (~BIT(1));
    }
    if (!(word_en & BIT(2))) {
        tmpaddr = start_addr;
        rtw_efuse_bt_access(padapter, _TRUE, start_addr++, 1, &data[4]);
        rtw_efuse_bt_access(padapter, _TRUE, start_addr++, 1, &data[5]);
        rtw_efuse_bt_access(padapter, _FALSE, tmpaddr, 1, &tmpdata[4]);
        rtw_efuse_bt_access(padapter, _FALSE, tmpaddr + 1, 1, &tmpdata[5]);
        if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
            badworden &= (~BIT(2));
    }
    if (!(word_en & BIT(3))) {
        tmpaddr = start_addr;
        rtw_efuse_bt_access(padapter, _TRUE, start_addr++, 1, &data[6]);
        rtw_efuse_bt_access(padapter, _TRUE, start_addr++, 1, &data[7]);
        rtw_efuse_bt_access(padapter, _FALSE, tmpaddr, 1, &tmpdata[6]);
        rtw_efuse_bt_access(padapter, _FALSE, tmpaddr + 1, 1, &tmpdata[7]);
        if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
            badworden &= (~BIT(3));
    }
    return badworden;
}
static void
hal_EfuseConstructPGPkt(
    u8                offset,
    u8                word_en,
    u8                *pData,
    PPGPKT_STRUCT    pTargetPkt)
{
    _rtw_memset(pTargetPkt->data, 0xFF, PGPKT_DATA_SIZE);
    pTargetPkt->offset = offset;
    pTargetPkt->word_en = word_en;
    efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
    pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
}
static u8
hal_EfusePgPacketWriteData(
    PADAPTER        pAdapter,
    u8                efuseType,
    u16                *pAddr,
    PPGPKT_STRUCT    pTargetPkt,
    u8                bPseudoTest)
{
    u16    efuse_addr;
    u8    badworden;
    efuse_addr = *pAddr;
    badworden = Hal_EfuseWordEnableDataWrite(pAdapter, efuse_addr + 1, pTargetPkt->word_en, pTargetPkt->data, bPseudoTest);
    if (badworden != 0x0F) {
        RTW_INFO("%s: Fail!!\n", __FUNCTION__);
        return _FALSE;
    } else
        RTW_INFO("%s: OK!!\n", __FUNCTION__);
    return _TRUE;
}
/* ***********************************************************
 *                Efuse related code
 * *********************************************************** */
static u8
hal_EfuseSwitchToBank(
    PADAPTER    padapter,
    u8            bank,
    u8            bPseudoTest)
{
    u8 bRet = _FALSE;
    u32 value32 = 0;
#ifdef HAL_EFUSE_MEMORY
    PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
    PEFUSE_HAL pEfuseHal = &pHalData->EfuseHal;
#endif
    RTW_INFO("%s: Efuse switch bank to %d\n", __FUNCTION__, bank);
    if (bPseudoTest) {
#ifdef HAL_EFUSE_MEMORY
        pEfuseHal->fakeEfuseBank = bank;
#else
        fakeEfuseBank = bank;
#endif
        bRet = _TRUE;
    } else {
        value32 = rtw_read32(padapter, 0x34);
        bRet = _TRUE;
        switch (bank) {
        case 0:
            value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
            break;
        case 1:
            value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_0);
            break;
        case 2:
            value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_1);
            break;
        case 3:
            value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_2);
            break;
        default:
            value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
            bRet = _FALSE;
            break;
        }
        rtw_write32(padapter, 0x34, value32);
    }
    return bRet;
}
#define EFUSE_CTRL                0x30        /* E-Fuse Control. */
/*  11/16/2008 MH Read one byte from real Efuse. */
u8
efuse_OneByteRead(
    IN    PADAPTER    pAdapter,
    IN    u16            addr,
    IN    u8            *data,
    IN    BOOLEAN        bPseudoTest)
{
    u32    tmpidx = 0;
    u8    bResult;
    u8    readbyte;
    HAL_DATA_TYPE    *pHalData = GET_HAL_DATA(pAdapter);
    if (IS_HARDWARE_TYPE_8723B(pAdapter) ||
        (IS_HARDWARE_TYPE_8192E(pAdapter) && (!IS_A_CUT(pHalData->version_id))) ||
        (IS_VENDOR_8188E_I_CUT_SERIES(pAdapter)) || (IS_CHIP_VENDOR_SMIC(pHalData->version_id))
       ) {
        /* <20130121, Kordan> For SMIC EFUSE specificatoin. */
        /* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8])     */
        /* phy_set_mac_reg(pAdapter, 0x34, BIT11, 0); */
        rtw_write16(pAdapter, 0x34, rtw_read16(pAdapter, 0x34) & (~BIT11));
    }
    /* -----------------e-fuse reg ctrl --------------------------------- */
    /* address             */
    rtw_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
    rtw_write8(pAdapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
           (rtw_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC));
    /* rtw_write8(pAdapter, EFUSE_CTRL+3,  0x72); */ /* read cmd     */
    /* Write bit 32 0 */
    readbyte = rtw_read8(pAdapter, EFUSE_CTRL + 3);
    rtw_write8(pAdapter, EFUSE_CTRL + 3, (readbyte & 0x7f));
    while (!(0x80 & rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 1000)) {
        rtw_mdelay_os(1);
        tmpidx++;
    }
    if (tmpidx < 100) {
        *data = rtw_read8(pAdapter, EFUSE_CTRL);
        bResult = _TRUE;
    } else {
        *data = 0xff;
        bResult = _FALSE;
        RTW_INFO("%s: [ERROR] addr=0x%x bResult=%d time out 1s !!!\n", __FUNCTION__, addr, bResult);
        RTW_INFO("%s: [ERROR] EFUSE_CTRL =0x%08x !!!\n", __FUNCTION__, rtw_read32(pAdapter, EFUSE_CTRL));
    }
    return bResult;
}
static u16
hal_EfuseGetCurrentSize_BT(
    PADAPTER    padapter,
    u8            bPseudoTest)
{
#ifdef HAL_EFUSE_MEMORY
    PHAL_DATA_TYPE    pHalData = GET_HAL_DATA(padapter);
    PEFUSE_HAL        pEfuseHal = &pHalData->EfuseHal;
#endif
    u16 btusedbytes;
    u16    efuse_addr;
    u8    bank, startBank;
    u8    hoffset = 0, hworden = 0;
    u8    efuse_data, word_cnts = 0;
    u16    retU2 = 0;
    u8 bContinual = _TRUE;
    btusedbytes = fakeBTEfuseUsedBytes;
    efuse_addr = (u16)((btusedbytes % EFUSE_BT_REAL_BANK_CONTENT_LEN));
    startBank = (u8)(1 + (btusedbytes / EFUSE_BT_REAL_BANK_CONTENT_LEN));
    RTW_INFO("%s: start from bank=%d addr=0x%X\n", __FUNCTION__, startBank, efuse_addr);
    retU2 = EFUSE_BT_REAL_CONTENT_LEN - EFUSE_PROTECT_BYTES_BANK;
    for (bank = startBank; bank < 3; bank++) {
        if (hal_EfuseSwitchToBank(padapter, bank, bPseudoTest) == _FALSE) {
            RTW_ERR("%s: switch bank(%d) Fail!!\n", __FUNCTION__, bank);
            /* bank = EFUSE_MAX_BANK; */
            break;
        }
        /* only when bank is switched we have to reset the efuse_addr. */
        if (bank != startBank)
            efuse_addr = 0;
        while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
            if (rtw_efuse_bt_access(padapter, _FALSE, efuse_addr, 1, &efuse_data) == _FALSE) {
                RTW_ERR("%s: efuse_OneByteRead Fail! addr=0x%X !!\n", __FUNCTION__, efuse_addr);
                /* bank = EFUSE_MAX_BANK; */
                break;
            }
            RTW_INFO("%s: efuse_OneByteRead ! addr=0x%X !efuse_data=0x%X! bank =%d\n", __FUNCTION__, efuse_addr, efuse_data, bank);
            if (efuse_data == 0xFF)
                break;
            if (EXT_HEADER(efuse_data)) {
                hoffset = GET_HDR_OFFSET_2_0(efuse_data);
                efuse_addr++;
                rtw_efuse_bt_access(padapter, _FALSE, efuse_addr, 1, &efuse_data);
                RTW_INFO("%s: efuse_OneByteRead EXT_HEADER ! addr=0x%X !efuse_data=0x%X! bank =%d\n", __FUNCTION__, efuse_addr, efuse_data, bank);
                if (ALL_WORDS_DISABLED(efuse_data)) {
                    efuse_addr++;
                    continue;
                }
                /*                hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); */
                hoffset |= ((efuse_data & 0xF0) >> 1);
                hworden = efuse_data & 0x0F;
            } else {
                hoffset = (efuse_data >> 4) & 0x0F;
                hworden =  efuse_data & 0x0F;
            }
            RTW_INFO(FUNC_ADPT_FMT": Offset=%d Worden=%#X\n",
                 FUNC_ADPT_ARG(padapter), hoffset, hworden);
            word_cnts = Efuse_CalculateWordCnts(hworden);
            /* read next header */
            efuse_addr += (word_cnts * 2) + 1;
        }
        /* Check if we need to check next bank efuse */
        if (efuse_addr < retU2)
            break;/* don't need to check next bank. */
    }
    retU2 = ((bank - 1) * EFUSE_BT_REAL_BANK_CONTENT_LEN) + efuse_addr;
    fakeBTEfuseUsedBytes = retU2;
    RTW_INFO("%s: CurrentSize=%d\n", __FUNCTION__, retU2);
    return retU2;
}
static u8
hal_BT_EfusePgCheckAvailableAddr(
    PADAPTER    pAdapter,
    u8        bPseudoTest)
{
    u16    max_available = EFUSE_BT_REAL_CONTENT_LEN - EFUSE_PROTECT_BYTES_BANK;
    u16    current_size = 0;
     RTW_INFO("%s: max_available=%d\n", __FUNCTION__, max_available);
    current_size = hal_EfuseGetCurrentSize_BT(pAdapter, bPseudoTest);
    if (current_size >= max_available) {
        RTW_INFO("%s: Error!! current_size(%d)>max_available(%d)\n", __FUNCTION__, current_size, max_available);
        return _FALSE;
    }
    return _TRUE;
}
u8 EfusePgPacketWrite_BT(
    PADAPTER    pAdapter,
    u8            offset,
    u8            word_en,
    u8            *pData,
    u8            bPseudoTest)
{
    PGPKT_STRUCT targetPkt;
    u16 startAddr = 0;
    u8 efuseType = EFUSE_BT;
    if (!hal_BT_EfusePgCheckAvailableAddr(pAdapter, bPseudoTest))
        return _FALSE;
    hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
    if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
        return _FALSE;
    if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
        return _FALSE;
    if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
        return _FALSE;
    return _TRUE;
}
#else /* !RTW_HALMAC */
/* ------------------------------------------------------------------------------ */
#define REG_EFUSE_CTRL        0x0030
#define EFUSE_CTRL            REG_EFUSE_CTRL        /* E-Fuse Control. */
/* ------------------------------------------------------------------------------ */
VOID efuse_PreUpdateAction(
    PADAPTER    pAdapter,
    pu4Byte    BackupRegs)
{
#if defined(CONFIG_RTL8812A)
    if (IS_HARDWARE_TYPE_8812AU(pAdapter)) {
        /* <20131115, Kordan> Turn off Rx to prevent from being busy when writing the EFUSE. (Asked by Chunchu.)*/
        BackupRegs[0] = phy_query_mac_reg(pAdapter, REG_RCR, bMaskDWord);
        BackupRegs[1] = phy_query_mac_reg(pAdapter, REG_RXFLTMAP0, bMaskDWord);
        BackupRegs[2] = phy_query_mac_reg(pAdapter, REG_RXFLTMAP0+4, bMaskDWord);
        BackupRegs[3] = phy_query_mac_reg(pAdapter, REG_AFE_MISC, bMaskDWord);
        PlatformEFIOWrite4Byte(pAdapter, REG_RCR, 0x1);
        PlatformEFIOWrite1Byte(pAdapter, REG_RXFLTMAP0, 0);
        PlatformEFIOWrite1Byte(pAdapter, REG_RXFLTMAP0+1, 0);
        PlatformEFIOWrite1Byte(pAdapter, REG_RXFLTMAP0+2, 0);
        PlatformEFIOWrite1Byte(pAdapter, REG_RXFLTMAP0+3, 0);
        PlatformEFIOWrite1Byte(pAdapter, REG_RXFLTMAP0+4, 0);
        PlatformEFIOWrite1Byte(pAdapter, REG_RXFLTMAP0+5, 0);
        /* <20140410, Kordan> 0x11 = 0x4E, lower down LX_SPS0 voltage. (Asked by Chunchu)*/
        phy_set_mac_reg(pAdapter, REG_AFE_MISC, bMaskByte1, 0x4E);
        }
#endif
}
VOID efuse_PostUpdateAction(
    PADAPTER    pAdapter,
    pu4Byte    BackupRegs)
{
#if defined(CONFIG_RTL8812A)
    if (IS_HARDWARE_TYPE_8812AU(pAdapter)) {
        /* <20131115, Kordan> Turn on Rx and restore the registers. (Asked by Chunchu.)*/
        phy_set_mac_reg(pAdapter, REG_RCR, bMaskDWord, BackupRegs[0]);
        phy_set_mac_reg(pAdapter, REG_RXFLTMAP0, bMaskDWord, BackupRegs[1]);
        phy_set_mac_reg(pAdapter, REG_RXFLTMAP0+4, bMaskDWord, BackupRegs[2]);
        phy_set_mac_reg(pAdapter, REG_AFE_MISC, bMaskDWord, BackupRegs[3]);
    }
#endif
}
BOOLEAN
Efuse_Read1ByteFromFakeContent(
    IN        PADAPTER    pAdapter,
    IN        u16        Offset,
    IN OUT    u8        *Value);
BOOLEAN
Efuse_Read1ByteFromFakeContent(
    IN        PADAPTER    pAdapter,
    IN        u16        Offset,
    IN OUT    u8        *Value)
{
    if (Offset >= EFUSE_MAX_HW_SIZE)
        return _FALSE;
    /* DbgPrint("Read fake content, offset = %d\n", Offset); */
    if (fakeEfuseBank == 0)
        *Value = fakeEfuseContent[Offset];
    else
        *Value = fakeBTEfuseContent[fakeEfuseBank - 1][Offset];
    return _TRUE;
}
BOOLEAN
Efuse_Write1ByteToFakeContent(
    IN        PADAPTER    pAdapter,
    IN        u16        Offset,
    IN        u8        Value);
BOOLEAN
Efuse_Write1ByteToFakeContent(
    IN        PADAPTER    pAdapter,
    IN        u16        Offset,
    IN        u8        Value)
{
    if (Offset >= EFUSE_MAX_HW_SIZE)
        return _FALSE;
    if (fakeEfuseBank == 0)
        fakeEfuseContent[Offset] = Value;
    else
        fakeBTEfuseContent[fakeEfuseBank - 1][Offset] = Value;
    return _TRUE;
}
/*-----------------------------------------------------------------------------
 * Function:    Efuse_PowerSwitch
 *
 * Overview:    When we want to enable write operation, we should change to
 *                pwr on state. When we stop write, we should switch to 500k mode
 *                and disable LDO 2.5V.
 *
 * Input:       NONE
 *
 * Output:      NONE
 *
 * Return:      NONE
 *
 * Revised History:
 * When            Who        Remark
 * 11/17/2008    MHC        Create Version 0.
 *
 *---------------------------------------------------------------------------*/
VOID
Efuse_PowerSwitch(
    IN    PADAPTER    pAdapter,
    IN    u8        bWrite,
    IN    u8        PwrState)
{
    pAdapter->hal_func.EfusePowerSwitch(pAdapter, bWrite, PwrState);
}
VOID
BTEfuse_PowerSwitch(
    IN    PADAPTER    pAdapter,
    IN    u8        bWrite,
    IN    u8        PwrState)
{
    if (pAdapter->hal_func.BTEfusePowerSwitch)
        pAdapter->hal_func.BTEfusePowerSwitch(pAdapter, bWrite, PwrState);
}
/*-----------------------------------------------------------------------------
 * Function:    efuse_GetCurrentSize
 *
 * Overview:    Get current efuse size!!!
 *
 * Input:       NONE
 *
 * Output:      NONE
 *
 * Return:      NONE
 *
 * Revised History:
 * When            Who        Remark
 * 11/16/2008    MHC        Create Version 0.
 *
 *---------------------------------------------------------------------------*/
u16
Efuse_GetCurrentSize(
    IN PADAPTER        pAdapter,
    IN u8            efuseType,
    IN BOOLEAN        bPseudoTest)
{
    u16 ret = 0;
    ret = pAdapter->hal_func.EfuseGetCurrentSize(pAdapter, efuseType, bPseudoTest);
    return ret;
}
/*
 *    Description:
 *        Execute E-Fuse read byte operation.
 *        Refered from SD1 Richard.
 *
 *    Assumption:
 *        1. Boot from E-Fuse and successfully auto-load.
 *        2. PASSIVE_LEVEL (USB interface)
 *
 *    Created by Roger, 2008.10.21.
 *   */
VOID
ReadEFuseByte(
    PADAPTER    Adapter,
    u16            _offset,
    u8            *pbuf,
    IN BOOLEAN    bPseudoTest)
{
    u32    value32;
    u8    readbyte;
    u16    retry;
    /* u32 start=rtw_get_current_time(); */
    if (bPseudoTest) {
        Efuse_Read1ByteFromFakeContent(Adapter, _offset, pbuf);
        return;
    }
    if (IS_HARDWARE_TYPE_8723B(Adapter)) {
        /* <20130121, Kordan> For SMIC S55 EFUSE specificatoin. */
        /* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */
        phy_set_mac_reg(Adapter, EFUSE_TEST, BIT11, 0);
    }
    /* Write Address */
    rtw_write8(Adapter, EFUSE_CTRL + 1, (_offset & 0xff));
    readbyte = rtw_read8(Adapter, EFUSE_CTRL + 2);
    rtw_write8(Adapter, EFUSE_CTRL + 2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
    /* Write bit 32 0 */
    readbyte = rtw_read8(Adapter, EFUSE_CTRL + 3);
    rtw_write8(Adapter, EFUSE_CTRL + 3, (readbyte & 0x7f));
    /* Check bit 32 read-ready */
    retry = 0;
    value32 = rtw_read32(Adapter, EFUSE_CTRL);
    /* while(!(((value32 >> 24) & 0xff) & 0x80)  && (retry<10)) */
    while (!(((value32 >> 24) & 0xff) & 0x80)  && (retry < 10000)) {
        value32 = rtw_read32(Adapter, EFUSE_CTRL);
        retry++;
    }
    /* 20100205 Joseph: Add delay suggested by SD1 Victor. */
    /* This fix the problem that Efuse read error in high temperature condition. */
    /* Designer says that there shall be some delay after ready bit is set, or the */
    /* result will always stay on last data we read. */
    rtw_udelay_os(50);
    value32 = rtw_read32(Adapter, EFUSE_CTRL);
    *pbuf = (u8)(value32 & 0xff);
    /* RTW_INFO("ReadEFuseByte _offset:%08u, in %d ms\n",_offset ,rtw_get_passing_time_ms(start)); */
}
/*
 *    Description:
 *        1. Execute E-Fuse read byte operation according as map offset and
 *            save to E-Fuse table.
 *        2. Refered from SD1 Richard.
 *
 *    Assumption:
 *        1. Boot from E-Fuse and successfully auto-load.
 *        2. PASSIVE_LEVEL (USB interface)
 *
 *    Created by Roger, 2008.10.21.
 *
 *    2008/12/12 MH    1. Reorganize code flow and reserve bytes. and add description.
 *                    2. Add efuse utilization collect.
 *    2008/12/22 MH    Read Efuse must check if we write section 1 data again!!! Sec1
 *                    write addr must be after sec5.
 *   */
VOID
efuse_ReadEFuse(
    PADAPTER    Adapter,
    u8        efuseType,
    u16        _offset,
    u16        _size_byte,
    u8    *pbuf,
    IN    BOOLEAN    bPseudoTest
);
VOID
efuse_ReadEFuse(
    PADAPTER    Adapter,
    u8        efuseType,
    u16        _offset,
    u16        _size_byte,
    u8    *pbuf,
    IN    BOOLEAN    bPseudoTest
)
{
    Adapter->hal_func.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
}
VOID
EFUSE_GetEfuseDefinition(
    IN        PADAPTER    pAdapter,
    IN        u8        efuseType,
    IN        u8        type,
    OUT        void        *pOut,
    IN        BOOLEAN        bPseudoTest
)
{
    pAdapter->hal_func.EFUSEGetEfuseDefinition(pAdapter, efuseType, type, pOut, bPseudoTest);
}
/*  11/16/2008 MH Read one byte from real Efuse. */
u8
efuse_OneByteRead(
    IN    PADAPTER    pAdapter,
    IN    u16            addr,
    IN    u8            *data,
    IN    BOOLEAN        bPseudoTest)
{
    u32    tmpidx = 0;
    u8    bResult;
    u8    readbyte;
    HAL_DATA_TYPE    *pHalData = GET_HAL_DATA(pAdapter);
    /* RTW_INFO("===> EFUSE_OneByteRead(), addr = %x\n", addr); */
    /* RTW_INFO("===> EFUSE_OneByteRead() start, 0x34 = 0x%X\n", rtw_read32(pAdapter, EFUSE_TEST)); */
    if (bPseudoTest) {
        bResult = Efuse_Read1ByteFromFakeContent(pAdapter, addr, data);
        return bResult;
    }
    if (IS_HARDWARE_TYPE_8723B(pAdapter) ||
        (IS_HARDWARE_TYPE_8192E(pAdapter) && (!IS_A_CUT(pHalData->version_id))) ||
        (IS_VENDOR_8188E_I_CUT_SERIES(pAdapter)) || (IS_CHIP_VENDOR_SMIC(pHalData->version_id))
       ) {
        /* <20130121, Kordan> For SMIC EFUSE specificatoin. */
        /* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8])     */
        /* phy_set_mac_reg(pAdapter, 0x34, BIT11, 0); */
        rtw_write16(pAdapter, 0x34, rtw_read16(pAdapter, 0x34) & (~BIT11));
    }
    /* -----------------e-fuse reg ctrl --------------------------------- */
    /* address             */
    rtw_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
    rtw_write8(pAdapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
           (rtw_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC));
    /* rtw_write8(pAdapter, EFUSE_CTRL+3,  0x72); */ /* read cmd     */
    /* Write bit 32 0 */
    readbyte = rtw_read8(pAdapter, EFUSE_CTRL + 3);
    rtw_write8(pAdapter, EFUSE_CTRL + 3, (readbyte & 0x7f));
    while (!(0x80 & rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 1000)) {
        rtw_mdelay_os(1);
        tmpidx++;
    }
    if (tmpidx < 100) {
        *data = rtw_read8(pAdapter, EFUSE_CTRL);
        bResult = _TRUE;
    } else {
        *data = 0xff;
        bResult = _FALSE;
        RTW_INFO("%s: [ERROR] addr=0x%x bResult=%d time out 1s !!!\n", __FUNCTION__, addr, bResult);
        RTW_INFO("%s: [ERROR] EFUSE_CTRL =0x%08x !!!\n", __FUNCTION__, rtw_read32(pAdapter, EFUSE_CTRL));
    }
    return bResult;
}
/*  11/16/2008 MH Write one byte to reald Efuse. */
u8
efuse_OneByteWrite(
    IN    PADAPTER    pAdapter,
    IN    u16            addr,
    IN    u8            data,
    IN    BOOLEAN        bPseudoTest)
{
    u8    tmpidx = 0;
    u8    bResult = _FALSE;
    u32 efuseValue = 0;
    HAL_DATA_TYPE    *pHalData = GET_HAL_DATA(pAdapter);
    /* RTW_INFO("===> EFUSE_OneByteWrite(), addr = %x data=%x\n", addr, data); */
    /* RTW_INFO("===> EFUSE_OneByteWrite() start, 0x34 = 0x%X\n", rtw_read32(pAdapter, EFUSE_TEST)); */
    if (bPseudoTest) {
        bResult = Efuse_Write1ByteToFakeContent(pAdapter, addr, data);
        return bResult;
    }
    Efuse_PowerSwitch(pAdapter, _TRUE, _TRUE);
    /* -----------------e-fuse reg ctrl ---------------------------------     */
    /* address             */
    efuseValue = rtw_read32(pAdapter, EFUSE_CTRL);
    efuseValue |= (BIT21 | BIT31);
    efuseValue &= ~(0x3FFFF);
    efuseValue |= ((addr << 8 | data) & 0x3FFFF);
    /* <20130227, Kordan> 8192E MP chip A-cut had better not set 0x34[11] until B-Cut. */
    if (IS_HARDWARE_TYPE_8723B(pAdapter) ||
        (IS_HARDWARE_TYPE_8192E(pAdapter) && (!IS_A_CUT(pHalData->version_id))) ||
        (IS_VENDOR_8188E_I_CUT_SERIES(pAdapter)) || (IS_CHIP_VENDOR_SMIC(pHalData->version_id))
       ) {
        /* <20130121, Kordan> For SMIC EFUSE specificatoin. */
        /* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */
        /* phy_set_mac_reg(pAdapter, 0x34, BIT11, 1); */
        rtw_write16(pAdapter, 0x34, rtw_read16(pAdapter, 0x34) | (BIT11));
        rtw_write32(pAdapter, EFUSE_CTRL, 0x90600000 | ((addr << 8 | data)));
    } else
        rtw_write32(pAdapter, EFUSE_CTRL, efuseValue);
    rtw_mdelay_os(1);
    while ((0x80 &  rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100)) {
        rtw_mdelay_os(1);
        tmpidx++;
    }
    if (tmpidx < 100)
        bResult = _TRUE;
    else {
        bResult = _FALSE;
        RTW_INFO("%s: [ERROR] addr=0x%x ,efuseValue=0x%x ,bResult=%d time out 1s !!!\n",
             __FUNCTION__, addr, efuseValue, bResult);
        RTW_INFO("%s: [ERROR] EFUSE_CTRL =0x%08x !!!\n", __FUNCTION__, rtw_read32(pAdapter, EFUSE_CTRL));
    }
    /* disable Efuse program enable */
    if (IS_HARDWARE_TYPE_8723B(pAdapter) ||
        (IS_HARDWARE_TYPE_8192E(pAdapter) && (!IS_A_CUT(pHalData->version_id))) ||
        (IS_VENDOR_8188E_I_CUT_SERIES(pAdapter)) || (IS_CHIP_VENDOR_SMIC(pHalData->version_id))
       )
        phy_set_mac_reg(pAdapter, EFUSE_TEST, BIT(11), 0);
    Efuse_PowerSwitch(pAdapter, _TRUE, _FALSE);
    return bResult;
}
int
Efuse_PgPacketRead(IN    PADAPTER    pAdapter,
           IN    u8            offset,
           IN    u8            *data,
           IN    BOOLEAN        bPseudoTest)
{
    int    ret = 0;
    ret =  pAdapter->hal_func.Efuse_PgPacketRead(pAdapter, offset, data, bPseudoTest);
    return ret;
}
int
Efuse_PgPacketWrite(IN    PADAPTER    pAdapter,
            IN    u8            offset,
            IN    u8            word_en,
            IN    u8            *data,
            IN    BOOLEAN        bPseudoTest)
{
    int ret;
    ret =  pAdapter->hal_func.Efuse_PgPacketWrite(pAdapter, offset, word_en, data, bPseudoTest);
    return ret;
}
int
Efuse_PgPacketWrite_BT(IN    PADAPTER    pAdapter,
               IN    u8            offset,
               IN    u8            word_en,
               IN    u8            *data,
               IN    BOOLEAN        bPseudoTest)
{
    int ret;
    ret =  pAdapter->hal_func.Efuse_PgPacketWrite_BT(pAdapter, offset, word_en, data, bPseudoTest);
    return ret;
}
u8
Efuse_WordEnableDataWrite(IN    PADAPTER    pAdapter,
              IN    u16        efuse_addr,
              IN    u8        word_en,
              IN    u8        *data,
              IN    BOOLEAN        bPseudoTest)
{
    u8    ret = 0;
    ret =  pAdapter->hal_func.Efuse_WordEnableDataWrite(pAdapter, efuse_addr, word_en, data, bPseudoTest);
    return ret;
}
static u8 efuse_read8(PADAPTER padapter, u16 address, u8 *value)
{
    return efuse_OneByteRead(padapter, address, value, _FALSE);
}
static u8 efuse_write8(PADAPTER padapter, u16 address, u8 *value)
{
    return efuse_OneByteWrite(padapter, address, *value, _FALSE);
}
/*
 * read/wirte raw efuse data
 */
u8 rtw_efuse_access(PADAPTER padapter, u8 bWrite, u16 start_addr, u16 cnts, u8 *data)
{
    int i = 0;
    u16    real_content_len = 0, max_available_size = 0;
    u8 res = _FAIL ;
    u8(*rw8)(PADAPTER, u16, u8 *);
    u32    backupRegs[4] = {0};
    EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (PVOID)&real_content_len, _FALSE);
    EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
    if (start_addr > real_content_len)
        return _FAIL;
    if (_TRUE == bWrite) {
        if ((start_addr + cnts) > max_available_size)
            return _FAIL;
        rw8 = &efuse_write8;
    } else
        rw8 = &efuse_read8;
    efuse_PreUpdateAction(padapter, backupRegs);
    Efuse_PowerSwitch(padapter, bWrite, _TRUE);
    /* e-fuse one byte read / write */
    for (i = 0; i < cnts; i++) {
        if (start_addr >= real_content_len) {
            res = _FAIL;
            break;
        }
        res = rw8(padapter, start_addr++, data++);
        if (_FAIL == res)
            break;
    }
    Efuse_PowerSwitch(padapter, bWrite, _FALSE);
    efuse_PostUpdateAction(padapter, backupRegs);
    return res;
}
/* ------------------------------------------------------------------------------ */
u16 efuse_GetMaxSize(PADAPTER padapter)
{
    u16    max_size;
    max_size = 0;
    EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI , TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_size, _FALSE);
    return max_size;
}
/* ------------------------------------------------------------------------------ */
u8 efuse_GetCurrentSize(PADAPTER padapter, u16 *size)
{
    Efuse_PowerSwitch(padapter, _FALSE, _TRUE);
    *size = Efuse_GetCurrentSize(padapter, EFUSE_WIFI, _FALSE);
    Efuse_PowerSwitch(padapter, _FALSE, _FALSE);
    return _SUCCESS;
}
/* ------------------------------------------------------------------------------ */
u16 efuse_bt_GetMaxSize(PADAPTER padapter)
{
    u16    max_size;
    max_size = 0;
    EFUSE_GetEfuseDefinition(padapter, EFUSE_BT , TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_size, _FALSE);
    return max_size;
}
u8 efuse_bt_GetCurrentSize(PADAPTER padapter, u16 *size)
{
    Efuse_PowerSwitch(padapter, _FALSE, _TRUE);
    *size = Efuse_GetCurrentSize(padapter, EFUSE_BT, _FALSE);
    Efuse_PowerSwitch(padapter, _FALSE, _FALSE);
    return _SUCCESS;
}
u8 rtw_efuse_map_read(PADAPTER padapter, u16 addr, u16 cnts, u8 *data)
{
    u16    mapLen = 0;
    EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, _FALSE);
    if ((addr + cnts) > mapLen)
        return _FAIL;
    Efuse_PowerSwitch(padapter, _FALSE, _TRUE);
    efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, _FALSE);
    Efuse_PowerSwitch(padapter, _FALSE, _FALSE);
    return _SUCCESS;
}
u8 rtw_BT_efuse_map_read(PADAPTER padapter, u16 addr, u16 cnts, u8 *data)
{
    u16    mapLen = 0;
    EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, _FALSE);
    if ((addr + cnts) > mapLen)
        return _FAIL;
    Efuse_PowerSwitch(padapter, _FALSE, _TRUE);
    efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, _FALSE);
    Efuse_PowerSwitch(padapter, _FALSE, _FALSE);
    return _SUCCESS;
}
/* ------------------------------------------------------------------------------ */
u8 rtw_efuse_map_write(PADAPTER padapter, u16 addr, u16 cnts, u8 *data)
{
#define RT_ASSERT_RET(expr)                                                \
    if (!(expr)) {                                                            \
        printk("Assertion failed! %s at ......\n", #expr);                            \
        printk("      ......%s,%s, line=%d\n",__FILE__, __FUNCTION__, __LINE__);    \
        return _FAIL;    \
    }
    u8    offset, word_en;
    u8    *map;
    u8    newdata[PGPKT_DATA_SIZE];
    s32    i, j, idx, chk_total_byte;
    u8    ret = _SUCCESS;
    u16    mapLen = 0, startAddr = 0, efuse_max_available_len = 0;
    u32    backupRegs[4] = {0};
    HAL_DATA_TYPE    *pHalData = GET_HAL_DATA(padapter);
    PEFUSE_HAL    pEfuseHal = &pHalData->EfuseHal;
    EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, _FALSE);
    EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &efuse_max_available_len, _FALSE);
    if ((addr + cnts) > mapLen)
        return _FAIL;
    RT_ASSERT_RET(PGPKT_DATA_SIZE == 8); /* have to be 8 byte alignment */
    RT_ASSERT_RET((mapLen & 0x7) == 0); /* have to be PGPKT_DATA_SIZE alignment for memcpy */
    map = rtw_zmalloc(mapLen);
    if (map == NULL)
        return _FAIL;
    _rtw_memset(map, 0xFF, mapLen);
    ret = rtw_efuse_map_read(padapter, 0, mapLen, map);
    if (ret == _FAIL)
        goto exit;
    if (padapter->registrypriv.boffefusemask == 0) {
        for (i = 0; i < cnts; i++) {
            if (padapter->registrypriv.bFileMaskEfuse == _TRUE) {
                if (rtw_file_efuse_IsMasked(padapter, addr + i))    /*use file efuse mask. */
                    data[i] = map[addr + i];
            } else {
                if (efuse_IsMasked(padapter, addr + i))
                    data[i] = map[addr + i];
            }
            RTW_INFO("%s , data[%d] = %x, map[addr+i]= %x\n", __func__, i, data[i], map[addr + i]);
        }
    }
    /*Efuse_PowerSwitch(padapter, _TRUE, _TRUE);*/
    chk_total_byte = 0;
    idx = 0;
    offset = (addr >> 3);
    while (idx < cnts) {
        word_en = 0xF;
        j = (addr + idx) & 0x7;
        for (i = j; i < PGPKT_DATA_SIZE && idx < cnts; i++, idx++) {
            if (data[idx] != map[addr + idx])
                word_en &= ~BIT(i >> 1);
        }
        if (word_en != 0xF) {
            chk_total_byte += Efuse_CalculateWordCnts(word_en) * 2;
            if (offset >= EFUSE_MAX_SECTION_BASE) /* Over EFUSE_MAX_SECTION 16 for 2 ByteHeader */
                chk_total_byte += 2;
            else
                chk_total_byte += 1;
        }
        offset++;
    }
    RTW_INFO("Total PG bytes Count = %d\n", chk_total_byte);
    rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
    if (startAddr == 0) {
        startAddr = Efuse_GetCurrentSize(padapter, EFUSE_WIFI, _FALSE);
        RTW_INFO("%s: Efuse_GetCurrentSize startAddr=%#X\n", __func__, startAddr);
    }
    RTW_DBG("%s: startAddr=%#X\n", __func__, startAddr);
    if ((startAddr + chk_total_byte) >= efuse_max_available_len) {
        RTW_INFO("%s: startAddr(0x%X) + PG data len %d >= efuse_max_available_len(0x%X)\n",
             __func__, startAddr, chk_total_byte, efuse_max_available_len);
        ret = _FAIL;
        goto exit;
    }
    efuse_PreUpdateAction(padapter, backupRegs);
    idx = 0;
    offset = (addr >> 3);
    while (idx < cnts) {
        word_en = 0xF;
        j = (addr + idx) & 0x7;
        _rtw_memcpy(newdata, &map[offset << 3], PGPKT_DATA_SIZE);
        for (i = j; i < PGPKT_DATA_SIZE && idx < cnts; i++, idx++) {
            if (data[idx] != map[addr + idx]) {
                word_en &= ~BIT(i >> 1);
                newdata[i] = data[idx];
#ifdef CONFIG_RTL8723B
                if (addr + idx == 0x8) {
                    if (IS_C_CUT(pHalData->version_id) || IS_B_CUT(pHalData->version_id)) {
                        if (pHalData->adjuseVoltageVal == 6) {
                            newdata[i] = map[addr + idx];
                            RTW_INFO(" %s ,\n adjuseVoltageVal = %d ,newdata[%d] = %x\n", __func__, pHalData->adjuseVoltageVal, i, newdata[i]);
                        }
                    }
                }
#endif
            }
        }
        if (word_en != 0xF) {
            ret = Efuse_PgPacketWrite(padapter, offset, word_en, newdata, _FALSE);
            RTW_INFO("offset=%x\n", offset);
            RTW_INFO("word_en=%x\n", word_en);
            for (i = 0; i < PGPKT_DATA_SIZE; i++)
                RTW_INFO("data=%x \t", newdata[i]);
            if (ret == _FAIL)
                break;
        }
        offset++;
    }
    /*Efuse_PowerSwitch(padapter, _TRUE, _FALSE);*/
    efuse_PostUpdateAction(padapter, backupRegs);
exit:
    rtw_mfree(map, mapLen);
    return ret;
}
u8 rtw_BT_efuse_map_write(PADAPTER padapter, u16 addr, u16 cnts, u8 *data)
{
#define RT_ASSERT_RET(expr)                                                \
    if (!(expr)) {                                                            \
        printk("Assertion failed! %s at ......\n", #expr);                            \
        printk("      ......%s,%s, line=%d\n",__FILE__, __FUNCTION__, __LINE__);    \
        return _FAIL;    \
    }
    u8    offset, word_en;
    u8    *map;
    u8    newdata[PGPKT_DATA_SIZE];
    s32    i = 0, j = 0, idx;
    u8    ret = _SUCCESS;
    u16    mapLen = 0;
    EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, _FALSE);
    if ((addr + cnts) > mapLen)
        return _FAIL;
    RT_ASSERT_RET(PGPKT_DATA_SIZE == 8); /* have to be 8 byte alignment */
    RT_ASSERT_RET((mapLen & 0x7) == 0); /* have to be PGPKT_DATA_SIZE alignment for memcpy */
    map = rtw_zmalloc(mapLen);
    if (map == NULL)
        return _FAIL;
    ret = rtw_BT_efuse_map_read(padapter, 0, mapLen, map);
    if (ret == _FAIL)
        goto exit;
    RTW_INFO("OFFSET\tVALUE(hex)\n");
    for (i = 0; i < 1024; i += 16) { /* set 512 because the iwpriv's extra size have limit 0x7FF */
        RTW_INFO("0x%03x\t", i);
        for (j = 0; j < 8; j++)
            RTW_INFO("%02X ", map[i + j]);
        RTW_INFO("\t");
        for (; j < 16; j++)
            RTW_INFO("%02X ", map[i + j]);
        RTW_INFO("\n");
    }
    RTW_INFO("\n");
    Efuse_PowerSwitch(padapter, _TRUE, _TRUE);
    idx = 0;
    offset = (addr >> 3);
    while (idx < cnts) {
        word_en = 0xF;
        j = (addr + idx) & 0x7;
        _rtw_memcpy(newdata, &map[offset << 3], PGPKT_DATA_SIZE);
        for (i = j; i < PGPKT_DATA_SIZE && idx < cnts; i++, idx++) {
            if (data[idx] != map[addr + idx]) {
                word_en &= ~BIT(i >> 1);
                newdata[i] = data[idx];
            }
        }
        if (word_en != 0xF) {
            RTW_INFO("offset=%x\n", offset);
            RTW_INFO("word_en=%x\n", word_en);
            RTW_INFO("%s: data=", __FUNCTION__);
            for (i = 0; i < PGPKT_DATA_SIZE; i++)
                RTW_INFO("0x%02X ", newdata[i]);
            RTW_INFO("\n");
            ret = Efuse_PgPacketWrite_BT(padapter, offset, word_en, newdata, _FALSE);
            if (ret == _FAIL)
                break;
        }
        offset++;
    }
    Efuse_PowerSwitch(padapter, _TRUE, _FALSE);
exit:
    rtw_mfree(map, mapLen);
    return ret;
}
/*-----------------------------------------------------------------------------
 * Function:    Efuse_ReadAllMap
 *
 * Overview:    Read All Efuse content
 *
 * Input:       NONE
 *
 * Output:      NONE
 *
 * Return:      NONE
 *
 * Revised History:
 * When            Who        Remark
 * 11/11/2008    MHC        Create Version 0.
 *
 *---------------------------------------------------------------------------*/
VOID
Efuse_ReadAllMap(
    IN        PADAPTER    pAdapter,
    IN        u8        efuseType,
    IN OUT    u8        *Efuse,
    IN        BOOLEAN        bPseudoTest);
VOID
Efuse_ReadAllMap(
    IN        PADAPTER    pAdapter,
    IN        u8        efuseType,
    IN OUT    u8        *Efuse,
    IN        BOOLEAN        bPseudoTest)
{
    u16    mapLen = 0;
    Efuse_PowerSwitch(pAdapter, _FALSE, _TRUE);
    EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, bPseudoTest);
    efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, bPseudoTest);
    Efuse_PowerSwitch(pAdapter, _FALSE, _FALSE);
}
/*-----------------------------------------------------------------------------
 * Function:    efuse_ShadowRead1Byte
 *            efuse_ShadowRead2Byte
 *            efuse_ShadowRead4Byte
 *
 * Overview:    Read from efuse init map by one/two/four bytes !!!!!
 *
 * Input:       NONE
 *
 * Output:      NONE
 *
 * Return:      NONE
 *
 * Revised History:
 * When            Who        Remark
 * 11/12/2008    MHC        Create Version 0.
 *
 *---------------------------------------------------------------------------*/
static VOID
efuse_ShadowRead1Byte(
    IN    PADAPTER    pAdapter,
    IN    u16        Offset,
    IN OUT    u8        *Value)
{
    PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
    *Value = pHalData->efuse_eeprom_data[Offset];
}    /* EFUSE_ShadowRead1Byte */
/* ---------------Read Two Bytes */
static VOID
efuse_ShadowRead2Byte(
    IN    PADAPTER    pAdapter,
    IN    u16        Offset,
    IN OUT    u16        *Value)
{
    PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
    *Value = pHalData->efuse_eeprom_data[Offset];
    *Value |= pHalData->efuse_eeprom_data[Offset + 1] << 8;
}    /* EFUSE_ShadowRead2Byte */
/* ---------------Read Four Bytes */
static VOID
efuse_ShadowRead4Byte(
    IN    PADAPTER    pAdapter,
    IN    u16        Offset,
    IN OUT    u32        *Value)
{
    PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
    *Value = pHalData->efuse_eeprom_data[Offset];
    *Value |= pHalData->efuse_eeprom_data[Offset + 1] << 8;
    *Value |= pHalData->efuse_eeprom_data[Offset + 2] << 16;
    *Value |= pHalData->efuse_eeprom_data[Offset + 3] << 24;
}    /* efuse_ShadowRead4Byte */
/*-----------------------------------------------------------------------------
 * Function:    efuse_ShadowWrite1Byte
 *            efuse_ShadowWrite2Byte
 *            efuse_ShadowWrite4Byte
 *
 * Overview:    Write efuse modify map by one/two/four byte.
 *
 * Input:       NONE
 *
 * Output:      NONE
 *
 * Return:      NONE
 *
 * Revised History:
 * When            Who        Remark
 * 11/12/2008    MHC        Create Version 0.
 *
 *---------------------------------------------------------------------------*/
#ifdef PLATFORM
static VOID
efuse_ShadowWrite1Byte(
    IN    PADAPTER    pAdapter,
    IN    u16        Offset,
    IN    u8        Value);
#endif /* PLATFORM */
static VOID
efuse_ShadowWrite1Byte(
    IN    PADAPTER    pAdapter,
    IN    u16        Offset,
    IN    u8        Value)
{
    PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
    pHalData->efuse_eeprom_data[Offset] = Value;
}    /* efuse_ShadowWrite1Byte */
/* ---------------Write Two Bytes */
static VOID
efuse_ShadowWrite2Byte(
    IN    PADAPTER    pAdapter,
    IN    u16        Offset,
    IN    u16        Value)
{
    PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
    pHalData->efuse_eeprom_data[Offset] = Value & 0x00FF;
    pHalData->efuse_eeprom_data[Offset + 1] = Value >> 8;
}    /* efuse_ShadowWrite1Byte */
/* ---------------Write Four Bytes */
static VOID
efuse_ShadowWrite4Byte(
    IN    PADAPTER    pAdapter,
    IN    u16        Offset,
    IN    u32        Value)
{
    PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
    pHalData->efuse_eeprom_data[Offset] = (u8)(Value & 0x000000FF);
    pHalData->efuse_eeprom_data[Offset + 1] = (u8)((Value >> 8) & 0x0000FF);
    pHalData->efuse_eeprom_data[Offset + 2] = (u8)((Value >> 16) & 0x00FF);
    pHalData->efuse_eeprom_data[Offset + 3] = (u8)((Value >> 24) & 0xFF);
}    /* efuse_ShadowWrite1Byte */
/*-----------------------------------------------------------------------------
 * Function:    EFUSE_ShadowRead
 *
 * Overview:    Read from efuse init map !!!!!
 *
 * Input:       NONE
 *
 * Output:      NONE
 *
 * Return:      NONE
 *
 * Revised History:
 * When            Who        Remark
 * 11/12/2008    MHC        Create Version 0.
 *
 *---------------------------------------------------------------------------*/
void
EFUSE_ShadowRead(
    IN        PADAPTER    pAdapter,
    IN        u8        Type,
    IN        u16        Offset,
    IN OUT    u32        *Value)
{
    if (Type == 1)
        efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
    else if (Type == 2)
        efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
    else if (Type == 4)
        efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
}    /* EFUSE_ShadowRead */
/*-----------------------------------------------------------------------------
 * Function:    EFUSE_ShadowWrite
 *
 * Overview:    Write efuse modify map for later update operation to use!!!!!
 *
 * Input:       NONE
 *
 * Output:      NONE
 *
 * Return:      NONE
 *
 * Revised History:
 * When            Who        Remark
 * 11/12/2008    MHC        Create Version 0.
 *
 *---------------------------------------------------------------------------*/
VOID
EFUSE_ShadowWrite(
    IN    PADAPTER    pAdapter,
    IN    u8        Type,
    IN    u16        Offset,
    IN OUT    u32        Value);
VOID
EFUSE_ShadowWrite(
    IN    PADAPTER    pAdapter,
    IN    u8        Type,
    IN    u16        Offset,
    IN OUT    u32        Value)
{
#if (MP_DRIVER == 0)
    return;
#endif
    if (pAdapter->registrypriv.mp_mode == 0)
        return;
    if (Type == 1)
        efuse_ShadowWrite1Byte(pAdapter, Offset, (u8)Value);
    else if (Type == 2)
        efuse_ShadowWrite2Byte(pAdapter, Offset, (u16)Value);
    else if (Type == 4)
        efuse_ShadowWrite4Byte(pAdapter, Offset, (u32)Value);
}    /* EFUSE_ShadowWrite */
VOID
Efuse_InitSomeVar(
    IN        PADAPTER    pAdapter
);
VOID
Efuse_InitSomeVar(
    IN        PADAPTER    pAdapter
)
{
    u8 i;
    _rtw_memset((PVOID)&fakeEfuseContent[0], 0xff, EFUSE_MAX_HW_SIZE);
    _rtw_memset((PVOID)&fakeEfuseInitMap[0], 0xff, EFUSE_MAX_MAP_LEN);
    _rtw_memset((PVOID)&fakeEfuseModifiedMap[0], 0xff, EFUSE_MAX_MAP_LEN);
    for (i = 0; i < EFUSE_MAX_BT_BANK; i++)
        _rtw_memset((PVOID)&BTEfuseContent[i][0], EFUSE_MAX_HW_SIZE, 0xff);
    _rtw_memset((PVOID)&BTEfuseInitMap[0], 0xff, EFUSE_BT_MAX_MAP_LEN);
    _rtw_memset((PVOID)&BTEfuseModifiedMap[0], 0xff, EFUSE_BT_MAX_MAP_LEN);
    for (i = 0; i < EFUSE_MAX_BT_BANK; i++)
        _rtw_memset((PVOID)&fakeBTEfuseContent[i][0], 0xff, EFUSE_MAX_HW_SIZE);
    _rtw_memset((PVOID)&fakeBTEfuseInitMap[0], 0xff, EFUSE_BT_MAX_MAP_LEN);
    _rtw_memset((PVOID)&fakeBTEfuseModifiedMap[0], 0xff, EFUSE_BT_MAX_MAP_LEN);
}
#endif /* !RTW_HALMAC */
/*  11/16/2008 MH Add description. Get current efuse area enabled word!!. */
u8
Efuse_CalculateWordCnts(IN u8    word_en)
{
    u8 word_cnts = 0;
    if (!(word_en & BIT(0)))
        word_cnts++; /* 0 : write enable */
    if (!(word_en & BIT(1)))
        word_cnts++;
    if (!(word_en & BIT(2)))
        word_cnts++;
    if (!(word_en & BIT(3)))
        word_cnts++;
    return word_cnts;
}
/*-----------------------------------------------------------------------------
 * Function:    efuse_WordEnableDataRead
 *
 * Overview:    Read allowed word in current efuse section data.
 *
 * Input:       NONE
 *
 * Output:      NONE
 *
 * Return:      NONE
 *
 * Revised History:
 * When            Who        Remark
 * 11/16/2008    MHC        Create Version 0.
 * 11/21/2008    MHC        Fix Write bug when we only enable late word.
 *
 *---------------------------------------------------------------------------*/
void
efuse_WordEnableDataRead(IN    u8    word_en,
             IN    u8    *sourdata,
             IN    u8    *targetdata)
{
    if (!(word_en & BIT(0))) {
        targetdata[0] = sourdata[0];
        targetdata[1] = sourdata[1];
    }
    if (!(word_en & BIT(1))) {
        targetdata[2] = sourdata[2];
        targetdata[3] = sourdata[3];
    }
    if (!(word_en & BIT(2))) {
        targetdata[4] = sourdata[4];
        targetdata[5] = sourdata[5];
    }
    if (!(word_en & BIT(3))) {
        targetdata[6] = sourdata[6];
        targetdata[7] = sourdata[7];
    }
}
/*-----------------------------------------------------------------------------
 * Function:    EFUSE_ShadowMapUpdate
 *
 * Overview:    Transfer current EFUSE content to shadow init and modify map.
 *
 * Input:       NONE
 *
 * Output:      NONE
 *
 * Return:      NONE
 *
 * Revised History:
 * When            Who        Remark
 * 11/13/2008    MHC        Create Version 0.
 *
 *---------------------------------------------------------------------------*/
void EFUSE_ShadowMapUpdate(
    IN PADAPTER    pAdapter,
    IN u8        efuseType,
    IN BOOLEAN    bPseudoTest)
{
    PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
    u16    mapLen = 0;
#ifdef RTW_HALMAC
    u8 *efuse_map = NULL;
    int err;
    mapLen = EEPROM_MAX_SIZE;
    efuse_map = pHalData->efuse_eeprom_data;
    /* efuse default content is 0xFF */
    _rtw_memset(efuse_map, 0xFF, EEPROM_MAX_SIZE);
    EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, bPseudoTest);
    if (!mapLen) {
        RTW_WARN("%s: <ERROR> fail to get efuse size!\n", __FUNCTION__);
        mapLen = EEPROM_MAX_SIZE;
    }
    if (mapLen > EEPROM_MAX_SIZE) {
        RTW_WARN("%s: <ERROR> size of efuse data(%d) is large than expected(%d)!\n",
             __FUNCTION__, mapLen, EEPROM_MAX_SIZE);
        mapLen = EEPROM_MAX_SIZE;
    }
    if (pHalData->bautoload_fail_flag == _FALSE) {
        err = rtw_halmac_read_logical_efuse_map(adapter_to_dvobj(pAdapter), efuse_map, mapLen);
        if (err)
            RTW_ERR("%s: <ERROR> fail to get efuse map!\n", __FUNCTION__);
    }
#else /* !RTW_HALMAC */
    EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, bPseudoTest);
    if (pHalData->bautoload_fail_flag == _TRUE)
        _rtw_memset(pHalData->efuse_eeprom_data, 0xFF, mapLen);
    else {
#ifdef CONFIG_ADAPTOR_INFO_CACHING_FILE
        if (_SUCCESS != retriveAdaptorInfoFile(pAdapter->registrypriv.adaptor_info_caching_file_path, pHalData->efuse_eeprom_data)) {
#endif
            Efuse_ReadAllMap(pAdapter, efuseType, pHalData->efuse_eeprom_data, bPseudoTest);
#ifdef CONFIG_ADAPTOR_INFO_CACHING_FILE
            storeAdaptorInfoFile(pAdapter->registrypriv.adaptor_info_caching_file_path, pHalData->efuse_eeprom_data);
        }
#endif
    }
    /* PlatformMoveMemory((PVOID)&pHalData->EfuseMap[EFUSE_MODIFY_MAP][0], */
    /* (PVOID)&pHalData->EfuseMap[EFUSE_INIT_MAP][0], mapLen); */
#endif /* !RTW_HALMAC */
    rtw_dump_cur_efuse(pAdapter);
} /* EFUSE_ShadowMapUpdate */
const u8 _mac_hidden_max_bw_to_hal_bw_cap[MAC_HIDDEN_MAX_BW_NUM] = {
    0,
    0,
    (BW_CAP_160M | BW_CAP_80M | BW_CAP_40M | BW_CAP_20M | BW_CAP_10M | BW_CAP_5M),
    (BW_CAP_5M),
    (BW_CAP_10M | BW_CAP_5M),
    (BW_CAP_20M | BW_CAP_10M | BW_CAP_5M),
    (BW_CAP_40M | BW_CAP_20M | BW_CAP_10M | BW_CAP_5M),
    (BW_CAP_80M | BW_CAP_40M | BW_CAP_20M | BW_CAP_10M | BW_CAP_5M),
};
const u8 _mac_hidden_proto_to_hal_proto_cap[MAC_HIDDEN_PROTOCOL_NUM] = {
    0,
    0,
    (PROTO_CAP_11N | PROTO_CAP_11G | PROTO_CAP_11B),
    (PROTO_CAP_11AC | PROTO_CAP_11N | PROTO_CAP_11G | PROTO_CAP_11B),
};
u8 mac_hidden_wl_func_to_hal_wl_func(u8 func)
{
    u8 wl_func = 0;
    if (func & BIT0)
        wl_func |= WL_FUNC_MIRACAST;
    if (func & BIT1)
        wl_func |= WL_FUNC_P2P;
    if (func & BIT2)
        wl_func |= WL_FUNC_TDLS;
    if (func & BIT3)
        wl_func |= WL_FUNC_FTM;
    return wl_func;
}
#ifdef PLATFORM_LINUX
#ifdef CONFIG_ADAPTOR_INFO_CACHING_FILE
/* #include <rtw_eeprom.h> */
int isAdaptorInfoFileValid(void)
{
    return _TRUE;
}
int storeAdaptorInfoFile(char *path, u8 *efuse_data)
{
    int ret = _SUCCESS;
    if (path && efuse_data) {
        ret = rtw_store_to_file(path, efuse_data, EEPROM_MAX_SIZE_512);
        if (ret == EEPROM_MAX_SIZE)
            ret = _SUCCESS;
        else
            ret = _FAIL;
    } else {
        RTW_INFO("%s NULL pointer\n", __FUNCTION__);
        ret =  _FAIL;
    }
    return ret;
}
int retriveAdaptorInfoFile(char *path, u8 *efuse_data)
{
    int ret = _SUCCESS;
    mm_segment_t oldfs;
    struct file *fp;
    if (path && efuse_data) {
        ret = rtw_retrieve_from_file(path, efuse_data, EEPROM_MAX_SIZE);
        if (ret == EEPROM_MAX_SIZE)
            ret = _SUCCESS;
        else
            ret = _FAIL;
#if 0
        if (isAdaptorInfoFileValid())
            return 0;
        else
            return _FAIL;
#endif
    } else {
        RTW_INFO("%s NULL pointer\n", __FUNCTION__);
        ret = _FAIL;
    }
    return ret;
}
#endif /* CONFIG_ADAPTOR_INFO_CACHING_FILE */
u8 rtw_efuse_file_read(PADAPTER padapter, u8 *filepatch, u8 *buf, u32 len)
{
    char *ptmpbuf = NULL, *ptr;
    u8 val8;
    u32 count, i, j;
    int err;
    u32 bufsize = 4096;
    ptmpbuf = rtw_zmalloc(bufsize);
    if (ptmpbuf == NULL)
        return _FALSE;
    count = rtw_retrieve_from_file(filepatch, ptmpbuf, bufsize);
    if (count <= 100) {
        rtw_mfree(ptmpbuf, bufsize);
        RTW_ERR("%s, filepatch %s, size=%d, FAIL!!\n", __FUNCTION__, filepatch, count);
        return _FALSE;
    }
    i = 0;
    j = 0;
    ptr = ptmpbuf;
    while ((j < len) && (i < count)) {
        if (ptmpbuf[i] == '\0')
            break;
        ptr = strpbrk(&ptmpbuf[i], " \t\n\r");
        if (ptr) {
            if (ptr == &ptmpbuf[i]) {
                i++;
                continue;
            }
            /* Add string terminating null */
            *ptr = 0;
        } else {
            ptr = &ptmpbuf[count-1];
        }
        err = sscanf(&ptmpbuf[i], "%hhx", &val8);
        if (err != 1) {
            RTW_WARN("Something wrong to parse efuse file, string=%s\n", &ptmpbuf[i]);
        } else {
            buf[j] = val8;
            RTW_DBG("i=%d, j=%d, 0x%02x\n", i, j, buf[j]);
            j++;
        }
        i = ptr - ptmpbuf + 1;
    }
    rtw_mfree(ptmpbuf, bufsize);
    RTW_INFO("%s, filepatch %s, size=%d, done\n", __FUNCTION__, filepatch, count);
    return _TRUE;
}
#ifdef CONFIG_EFUSE_CONFIG_FILE
u32 rtw_read_efuse_from_file(const char *path, u8 *buf, int map_size)
{
    u32 i;
    u8 c;
    u8 temp[3];
    u8 temp_i;
    u8 end = _FALSE;
    u32 ret = _FAIL;
    u8 *file_data = NULL;
    u32 file_size, read_size, pos = 0;
    u8 *map = NULL;
    if (rtw_is_file_readable_with_size(path, &file_size) != _TRUE) {
        RTW_PRINT("%s %s is not readable\n", __func__, path);
        goto exit;
    }
    file_data = rtw_vmalloc(file_size);
    if (!file_data) {
        RTW_ERR("%s rtw_vmalloc(%d) fail\n", __func__, file_size);
        goto exit;
    }
    read_size = rtw_retrieve_from_file(path, file_data, file_size);
    if (read_size == 0) {
        RTW_ERR("%s read from %s fail\n", __func__, path);
        goto exit;
    }
    map = rtw_vmalloc(map_size);
    if (!map) {
        RTW_ERR("%s rtw_vmalloc(%d) fail\n", __func__, map_size);
        goto exit;
    }
    _rtw_memset(map, 0xff, map_size);
    temp[2] = 0; /* end of string '\0' */
    for (i = 0 ; i < map_size ; i++) {
        temp_i = 0;
        while (1) {
            if (pos >= read_size) {
                end = _TRUE;
                break;
            }
            c = file_data[pos++];
            /* bypass spece or eol or null before first hex digit */
            if (temp_i == 0 && (is_eol(c) == _TRUE || is_space(c) == _TRUE || is_null(c) == _TRUE))
                continue;
            if (IsHexDigit(c) == _FALSE) {
                RTW_ERR("%s invalid 8-bit hex format for offset:0x%03x\n", __func__, i);
                goto exit;
            }
            temp[temp_i++] = c;
            if (temp_i == 2) {
                /* parse value */
                if (sscanf(temp, "%hhx", &map[i]) != 1) {
                    RTW_ERR("%s sscanf fail for offset:0x%03x\n", __func__, i);
                    goto exit;
                }
                break;
            }
        }
        if (end == _TRUE) {
            if (temp_i != 0) {
                RTW_ERR("%s incomplete 8-bit hex format for offset:0x%03x\n", __func__, i);
                goto exit;
            }
            break;
        }
    }
    RTW_PRINT("efuse file:%s, 0x%03x byte content read\n", path, i);
    _rtw_memcpy(buf, map, map_size);
    ret = _SUCCESS;
exit:
    if (file_data)
        rtw_vmfree(file_data, file_size);
    if (map)
        rtw_vmfree(map, map_size);
    return ret;
}
u32 rtw_read_macaddr_from_file(const char *path, u8 *buf)
{
    u32 i;
    u8 temp[3];
    u32 ret = _FAIL;
    u8 file_data[17];
    u32 read_size, pos = 0;
    u8 addr[ETH_ALEN];
    if (rtw_is_file_readable(path) != _TRUE) {
        RTW_PRINT("%s %s is not readable\n", __func__, path);
        goto exit;
    }
    read_size = rtw_retrieve_from_file(path, file_data, 17);
    if (read_size != 17) {
        RTW_ERR("%s read from %s fail\n", __func__, path);
        goto exit;
    }
    temp[2] = 0; /* end of string '\0' */
    for (i = 0 ; i < ETH_ALEN ; i++) {
        if (IsHexDigit(file_data[i * 3]) == _FALSE || IsHexDigit(file_data[i * 3 + 1]) == _FALSE) {
            RTW_ERR("%s invalid 8-bit hex format for address offset:%u\n", __func__, i);
            goto exit;
        }
        if (i < ETH_ALEN - 1 && file_data[i * 3 + 2] != ':') {
            RTW_ERR("%s invalid separator after address offset:%u\n", __func__, i);
            goto exit;
        }
        temp[0] = file_data[i * 3];
        temp[1] = file_data[i * 3 + 1];
        if (sscanf(temp, "%hhx", &addr[i]) != 1) {
            RTW_ERR("%s sscanf fail for address offset:0x%03x\n", __func__, i);
            goto exit;
        }
    }
    _rtw_memcpy(buf, addr, ETH_ALEN);
    RTW_PRINT("wifi_mac file: %s\n", path);
#ifdef CONFIG_RTW_DEBUG
    RTW_INFO(MAC_FMT"\n", MAC_ARG(buf));
#endif
    ret = _SUCCESS;
exit:
    return ret;
}
#endif /* CONFIG_EFUSE_CONFIG_FILE */
#endif /* PLATFORM_LINUX */
linux-bsp/drivers/rtl8188eus/core/rtw_ap.c
New file
Diff too large
linux-bsp/drivers/rtl8188eus/core/rtw_beamforming.c
New file
@@ -0,0 +1,3157 @@
/******************************************************************************
 *
 * Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 *
 ******************************************************************************/
#define _RTW_BEAMFORMING_C_
#include <drv_types.h>
#include <hal_data.h>
#ifdef CONFIG_BEAMFORMING
#ifdef RTW_BEAMFORMING_VERSION_2
struct ndpa_sta_info {
    u16 aid:12;
    u16 feedback_type:1;
    u16 nc_index:3;
};
static void _get_txvector_parameter(PADAPTER adapter, struct sta_info *sta, u8 *g_id, u16 *p_aid)
{
    struct mlme_priv *mlme;
    u16 aid;
    u8 *bssid;
    u16 val16;
    u8 i;
    mlme = &adapter->mlmepriv;
    if (check_fwstate(mlme, WIFI_AP_STATE)) {
        /*
         * Sent by an AP and addressed to a STA associated with that AP
         * or sent by a DLS or TDLS STA in a direct path to
         * a DLS or TDLS peer STA
         */
        aid = sta->aid;
        bssid = adapter_mac_addr(adapter);
        RTW_INFO("%s: AID=0x%x BSSID=" MAC_FMT "\n",
             __FUNCTION__, sta->aid, MAC_ARG(bssid));
        /* AID[0:8] */
        aid &= 0x1FF;
        /* BSSID[44:47] xor BSSID[40:43] */
        val16 = ((bssid[5] & 0xF0) >> 4) ^ (bssid[5] & 0xF);
        /* (dec(AID[0:8]) + dec(BSSID)*2^5) mod 2^9 */
        *p_aid = (aid + (val16 << 5)) & 0x1FF;
        *g_id = 63;
    } else if ((check_fwstate(mlme, WIFI_ADHOC_STATE) == _TRUE)
           || (check_fwstate(mlme, WIFI_ADHOC_MASTER_STATE) == _TRUE)) {
        /*
         * Otherwise, includes
         * 1. Sent to an IBSS STA
         * 2. Sent by an AP to a non associated STA
         * 3. Sent to a STA for which it is not known
         *    which condition is applicable
         */
        *p_aid = 0;
        *g_id = 63;
    } else {
        /* Addressed to AP */
        bssid = sta->hwaddr;
        RTW_INFO("%s: BSSID=" MAC_FMT "\n", __FUNCTION__, MAC_ARG(bssid));
        /* BSSID[39:47] */
        *p_aid = (bssid[5] << 1) | (bssid[4] >> 7);
        *g_id = 0;
    }
    RTW_INFO("%s: GROUP_ID=0x%02x PARTIAL_AID=0x%04x\n",
         __FUNCTION__, *g_id, *p_aid);
}
/*
 * Parameters
 *    adapter        struct _adapter*
 *    sta        struct sta_info*
 *    sta_bf_cap    beamforming capabe of sta
 *    sounding_dim    Number of Sounding Dimensions
 *    comp_steering    Compressed Steering Number of Beamformer Antennas Supported
 */
static void _get_sta_beamform_cap(PADAPTER adapter, struct sta_info *sta,
    u8 *sta_bf_cap, u8 *sounding_dim, u8 *comp_steering)
{
    struct beamforming_info *info;
    struct ht_priv *ht;
#ifdef CONFIG_80211AC_VHT
    struct vht_priv *vht;
#endif /* CONFIG_80211AC_VHT */
    u16 bf_cap;
    *sta_bf_cap = 0;
    *sounding_dim = 0;
    *comp_steering = 0;
    info = GET_BEAMFORM_INFO(adapter);
    ht = &adapter->mlmepriv.htpriv;
#ifdef CONFIG_80211AC_VHT
    vht = &adapter->mlmepriv.vhtpriv;
#endif /* CONFIG_80211AC_VHT */
    if (is_supported_ht(sta->wireless_mode) == _TRUE) {
        /* HT */
        bf_cap = ht->beamform_cap;
        if (TEST_FLAG(bf_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE)) {
            info->beamforming_cap |= BEAMFORMEE_CAP_HT_EXPLICIT;
            *sta_bf_cap |= BEAMFORMER_CAP_HT_EXPLICIT;
            *sounding_dim = (bf_cap & BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP) >> 6;
        }
        if (TEST_FLAG(bf_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) {
            info->beamforming_cap |= BEAMFORMER_CAP_HT_EXPLICIT;
            *sta_bf_cap |= BEAMFORMEE_CAP_HT_EXPLICIT;
            *comp_steering = (bf_cap & BEAMFORMING_HT_BEAMFORMER_STEER_NUM) >> 4;
        }
    }
#ifdef CONFIG_80211AC_VHT
    if (is_supported_vht(sta->wireless_mode) == _TRUE) {
        /* VHT */
        bf_cap = vht->beamform_cap;
        /* We are SU Beamformee because the STA is SU Beamformer */
        if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)) {
            info->beamforming_cap |= BEAMFORMEE_CAP_VHT_SU;
            *sta_bf_cap |= BEAMFORMER_CAP_VHT_SU;
            /* We are MU Beamformee because the STA is MU Beamformer */
            if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)) {
                info->beamforming_cap |= BEAMFORMEE_CAP_VHT_MU;
                *sta_bf_cap |= BEAMFORMER_CAP_VHT_MU;
            }
            *sounding_dim = (bf_cap & BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM) >> 12;
        }
        /* We are SU Beamformer because the STA is SU Beamformee */
        if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) {
            info->beamforming_cap |= BEAMFORMER_CAP_VHT_SU;
            *sta_bf_cap |= BEAMFORMEE_CAP_VHT_SU;
            /* We are MU Beamformer because the STA is MU Beamformee */
            if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)) {
                info->beamforming_cap |= BEAMFORMER_CAP_VHT_MU;
                *sta_bf_cap |= BEAMFORMEE_CAP_VHT_MU;
            }
            *comp_steering = (bf_cap & BEAMFORMING_VHT_BEAMFORMER_STS_CAP) >> 8;
        }
    }
#endif /* CONFIG_80211AC_VHT */
}
static u8 _send_ht_ndpa_packet(PADAPTER adapter, u8 *ra, CHANNEL_WIDTH bw)
{
    /* General */
    struct xmit_priv        *pxmitpriv;
    struct mlme_ext_priv        *pmlmeext;
    struct mlme_ext_info        *pmlmeinfo;
    struct xmit_frame        *pmgntframe;
    /* Beamforming */
    struct beamforming_info        *info;
    struct beamformee_entry        *bfee;
    struct ndpa_sta_info        sta_info;
    u8 ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xE0, 0x4C};
    /* MISC */
    struct pkt_attrib        *attrib;
    struct rtw_ieee80211_hdr    *pwlanhdr;
    enum MGN_RATE txrate;
    u8 *pframe;
    u16 duration = 0;
    u8 aSifsTime = 0;
    RTW_INFO("+%s: Send to " MAC_FMT "\n", __FUNCTION__, MAC_ARG(ra));
    pxmitpriv = &adapter->xmitpriv;
    pmlmeext = &adapter->mlmeextpriv;
    pmlmeinfo = &pmlmeext->mlmext_info;
    bfee = rtw_bf_bfee_get_entry_by_addr(adapter, ra);
    if (!bfee) {
        RTW_ERR("%s: Cann't find beamformee entry!\n", __FUNCTION__);
        return _FALSE;
    }
    pmgntframe = alloc_mgtxmitframe(pxmitpriv);
    if (!pmgntframe) {
        RTW_ERR("%s: alloc mgnt frame fail!\n", __FUNCTION__);
        return _FALSE;
    }
    txrate = beamforming_get_htndp_tx_rate(GET_PDM_ODM(adapter), bfee->comp_steering_num_of_bfer);
    /* update attribute */
    attrib = &pmgntframe->attrib;
    update_mgntframe_attrib(adapter, attrib);
    /*attrib->type = WIFI_MGT_TYPE;*/ /* set in update_mgntframe_attrib() */
    attrib->subtype = WIFI_ACTION_NOACK;
    attrib->bwmode = bw;
    /*attrib->qsel = QSLT_MGNT;*/ /* set in update_mgntframe_attrib() */
    attrib->order = 1;
    attrib->rate = (u8)txrate;
    attrib->bf_pkt_type = 0;
    _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
    pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
    pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
    /* Frame control */
    pwlanhdr->frame_ctl = 0;
    set_frame_sub_type(pframe, attrib->subtype);
    set_order_bit(pframe);
    /* Duration */
    if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
        aSifsTime = 10;
    else
        aSifsTime = 16;
    duration = 2 * aSifsTime + 40;
    if (bw == CHANNEL_WIDTH_40)
        duration += 87;
    else
        duration += 180;
    set_duration(pframe, duration);
    /* DA */
    _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
    /* SA */
    _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
    /* BSSID */
    _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
    /* HT control field */
    SET_HT_CTRL_CSI_STEERING(pframe + 24, 3);
    SET_HT_CTRL_NDP_ANNOUNCEMENT(pframe + 24, 1);
    /*
     * Frame Body
     * Category field: vender-specific value, 0x7F
     * OUI: 0x00E04C
     */
    _rtw_memcpy(pframe + 28, ActionHdr, 4);
    attrib->pktlen = 32;
    attrib->last_txcmdsz = attrib->pktlen;
    dump_mgntframe(adapter, pmgntframe);
    return _TRUE;
}
static u8 _send_vht_ndpa_packet(PADAPTER adapter, u8 *ra, u16 aid, CHANNEL_WIDTH bw)
{
    /* General */
    struct xmit_priv        *pxmitpriv;
    struct mlme_ext_priv        *pmlmeext;
    struct xmit_frame        *pmgntframe;
    /* Beamforming */
    struct beamforming_info        *info;
    struct beamformee_entry        *bfee;
    struct ndpa_sta_info        sta_info;
    /* MISC */
    struct pkt_attrib        *attrib;
    struct rtw_ieee80211_hdr    *pwlanhdr;
    u8 *pframe;
    enum MGN_RATE txrate;
    u16 duration = 0;
    u8 sequence = 0, aSifsTime = 0;
    RTW_INFO("+%s: Send to " MAC_FMT "\n", __FUNCTION__, MAC_ARG(ra));
    pxmitpriv = &adapter->xmitpriv;
    pmlmeext = &adapter->mlmeextpriv;
    info = GET_BEAMFORM_INFO(adapter);
    bfee = rtw_bf_bfee_get_entry_by_addr(adapter, ra);
    if (!bfee) {
        RTW_ERR("%s: Cann't find beamformee entry!\n", __FUNCTION__);
        return _FALSE;
    }
    pmgntframe = alloc_mgtxmitframe(pxmitpriv);
    if (!pmgntframe) {
        RTW_ERR("%s: alloc mgnt frame fail!\n", __FUNCTION__);
        return _FALSE;
    }
    txrate = beamforming_get_vht_ndp_tx_rate(GET_PDM_ODM(adapter), bfee->comp_steering_num_of_bfer);
    /* update attribute */
    attrib = &pmgntframe->attrib;
    update_mgntframe_attrib(adapter, attrib);
    /*pattrib->type = WIFI_MGT_TYPE;*/ /* set in update_mgntframe_attrib() */
    attrib->subtype = WIFI_NDPA;
    attrib->bwmode = bw;
    /*attrib->qsel = QSLT_MGNT;*/ /* set in update_mgntframe_attrib() */
    attrib->rate = (u8)txrate;
    attrib->bf_pkt_type = 0;
    _rtw_memset(pmgntframe->buf_addr, 0, TXDESC_OFFSET + WLANHDR_OFFSET);
    pframe = pmgntframe->buf_addr + TXDESC_OFFSET;
    pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
    /* Frame control */
    pwlanhdr->frame_ctl = 0;
    set_frame_sub_type(pframe, attrib->subtype);
    /* Duration */
    if (is_supported_5g(pmlmeext->cur_wireless_mode) || is_supported_ht(pmlmeext->cur_wireless_mode))
        aSifsTime = 16;
    else
        aSifsTime = 10;
    duration = 2 * aSifsTime + 44;
    if (bw == CHANNEL_WIDTH_80)
        duration += 40;
    else if (bw == CHANNEL_WIDTH_40)
        duration += 87;
    else
        duration += 180;
    set_duration(pframe, duration);
    /* RA */
    _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
    /* TA */
    _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
    /* Sounding Sequence, bit0~1 is reserved */
    sequence = info->sounding_sequence << 2;
    if (info->sounding_sequence >= 0x3f)
        info->sounding_sequence = 0;
    else
        info->sounding_sequence++;
    _rtw_memcpy(pframe + 16, &sequence, 1);
    /* STA Info */
    /*
     * "AID12" Equal to 0 if the STA is an AP, mesh STA or
     * STA that is a member of an IBSS
     */
    if (check_fwstate(&adapter->mlmepriv, WIFI_AP_STATE) == _FALSE)
        aid = 0;
    sta_info.aid = aid;
    /* "Feedback Type" set to 0 for SU */
    sta_info.feedback_type = 0;
    /* "Nc Index" reserved if the Feedback Type field indicates SU */
    sta_info.nc_index = 0;
    _rtw_memcpy(pframe + 17, (u8 *)&sta_info, 2);
    attrib->pktlen = 19;
    attrib->last_txcmdsz = attrib->pktlen;
    dump_mgntframe(adapter, pmgntframe);
    return _TRUE;
}
static u8 _send_vht_mu_ndpa_packet(PADAPTER adapter, CHANNEL_WIDTH bw)
{
    /* General */
    struct xmit_priv        *pxmitpriv;
    struct mlme_ext_priv        *pmlmeext;
    struct xmit_frame        *pmgntframe;
    /* Beamforming */
    struct beamforming_info        *info;
    struct sounding_info        *sounding;
    struct beamformee_entry        *bfee;
    struct ndpa_sta_info        sta_info;
    /* MISC */
    struct pkt_attrib        *attrib;
    struct rtw_ieee80211_hdr    *pwlanhdr;
    enum MGN_RATE txrate;
    u8 *pframe;
    u8 *ra = NULL;
    u16 duration = 0;
    u8 sequence = 0, aSifsTime = 0;
    u8 i;
    RTW_INFO("+%s\n", __FUNCTION__);
    pxmitpriv = &adapter->xmitpriv;
    pmlmeext = &adapter->mlmeextpriv;
    info = GET_BEAMFORM_INFO(adapter);
    sounding = &info->sounding_info;
    txrate = MGN_VHT2SS_MCS0;
    /*
     * Fill the first MU BFee entry (STA1) MAC addr to destination address then
     * HW will change A1 to broadcast addr.
     * 2015.05.28. Suggested by SD1 Chunchu.
     */
    bfee = &info->bfee_entry[sounding->mu_sounding_list[0]];
    ra = bfee->mac_addr;
    pmgntframe = alloc_mgtxmitframe(pxmitpriv);
    if (!pmgntframe) {
        RTW_ERR("%s: alloc mgnt frame fail!\n", __FUNCTION__);
        return _FALSE;
    }
    /* update attribute */
    attrib = &pmgntframe->attrib;
    update_mgntframe_attrib(adapter, attrib);
    /*attrib->type = WIFI_MGT_TYPE;*/ /* set in update_mgntframe_attrib() */
    attrib->subtype = WIFI_NDPA;
    attrib->bwmode = bw;
    /*attrib->qsel = QSLT_MGNT;*/ /* set in update_mgntframe_attrib() */
    attrib->rate = (u8)txrate;
    /* Set TxBFPktType of Tx desc to unicast type if there is only one MU STA for HW design */
    if (info->sounding_info.candidate_mu_bfee_cnt > 1)
        attrib->bf_pkt_type = 1;
    else
        attrib->bf_pkt_type = 0;
    _rtw_memset(pmgntframe->buf_addr, 0, TXDESC_OFFSET + WLANHDR_OFFSET);
    pframe = pmgntframe->buf_addr + TXDESC_OFFSET;
    pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
    /* Frame control */
    pwlanhdr->frame_ctl = 0;
    set_frame_sub_type(pframe, attrib->subtype);
    /* Duration */
    if (is_supported_5g(pmlmeext->cur_wireless_mode) || is_supported_ht(pmlmeext->cur_wireless_mode))
        aSifsTime = 16;
    else
        aSifsTime = 10;
    duration = 2 * aSifsTime + 44;
    if (bw == CHANNEL_WIDTH_80)
        duration += 40;
    else if (bw == CHANNEL_WIDTH_40)
        duration += 87;
    else
        duration += 180;
    set_duration(pframe, duration);
    /* RA */
    _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
    /* TA */
    _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
    /* Sounding Sequence, bit0~1 is reserved */
    sequence = info->sounding_sequence << 2;
    if (info->sounding_sequence >= 0x3f)
        info->sounding_sequence = 0;
    else
        info->sounding_sequence++;
    _rtw_memcpy(pframe + 16, &sequence, 1);
    attrib->pktlen = 17;
    /*
     * Construct STA info. for multiple STAs
     * STA Info1, ..., STA Info n
     */
    for (i = 0; i < sounding->candidate_mu_bfee_cnt; i++) {
        bfee = &info->bfee_entry[sounding->mu_sounding_list[i]];
        sta_info.aid = bfee->aid;
        sta_info.feedback_type = 1; /* 1'b1: MU */
        sta_info.nc_index = 0;
        _rtw_memcpy(pframe + attrib->pktlen, (u8 *)&sta_info, 2);
        attrib->pktlen += 2;
    }
    attrib->last_txcmdsz = attrib->pktlen;
    dump_mgntframe(adapter, pmgntframe);
    return _TRUE;
}
static u8 _send_bf_report_poll(PADAPTER adapter, u8 *ra, u8 bFinalPoll)
{
    /* General */
    struct xmit_priv *pxmitpriv;
    struct xmit_frame *pmgntframe;
    /* MISC */
    struct pkt_attrib *attrib;
    struct rtw_ieee80211_hdr *pwlanhdr;
    u8 *pframe;
    RTW_INFO("+%s: Send to " MAC_FMT "\n", __FUNCTION__, MAC_ARG(ra));
    pxmitpriv = &adapter->xmitpriv;
    pmgntframe = alloc_mgtxmitframe(pxmitpriv);
    if (!pmgntframe) {
        RTW_ERR("%s: alloc mgnt frame fail!\n", __FUNCTION__);
        return _FALSE;
    }
    /* update attribute */
    attrib = &pmgntframe->attrib;
    update_mgntframe_attrib(adapter, attrib);
    /*attrib->type = WIFI_MGT_TYPE;*/ /* set in update_mgntframe_attrib() */
    attrib->subtype = WIFI_BF_REPORT_POLL;
    attrib->bwmode = CHANNEL_WIDTH_20;
    /*attrib->qsel = QSLT_MGNT;*/ /* set in update_mgntframe_attrib() */
    attrib->rate = MGN_6M;
    if (bFinalPoll)
        attrib->bf_pkt_type = 3;
    else
        attrib->bf_pkt_type = 2;
    _rtw_memset(pmgntframe->buf_addr, 0, TXDESC_OFFSET + WLANHDR_OFFSET);
    pframe = pmgntframe->buf_addr + TXDESC_OFFSET;
    pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
    /* Frame control */
    pwlanhdr->frame_ctl = 0;
    set_frame_sub_type(pframe, attrib->subtype);
    /* Duration */
    set_duration(pframe, 100);
    /* RA */
    _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
    /* TA */
    _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
    /* Feedback Segment Retransmission Bitmap */
    pframe[16] = 0xFF;
    attrib->pktlen = 17;
    attrib->last_txcmdsz = attrib->pktlen;
    dump_mgntframe(adapter, pmgntframe);
    return _TRUE;
}
static void _sounding_update_min_period(PADAPTER adapter, u16 period, u8 leave)
{
    struct beamforming_info *info;
    struct beamformee_entry *bfee;
    u8 i = 0;
    u16 min_val = 0xFFFF;
    info = GET_BEAMFORM_INFO(adapter);
    if (_TRUE == leave) {
        /*
         * When a BFee left,
         * we need to find the latest min sounding period
         * from the remaining BFees
         */
        for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
            bfee = &info->bfee_entry[i];
            if ((bfee->used == _TRUE)
                && (bfee->sound_period < min_val))
                min_val = bfee->sound_period;
        }
        if (min_val == 0xFFFF)
            info->sounding_info.min_sounding_period = 0;
        else
            info->sounding_info.min_sounding_period = min_val;
    } else {
        if ((info->sounding_info.min_sounding_period == 0)
            || (period < info->sounding_info.min_sounding_period))
            info->sounding_info.min_sounding_period = period;
    }
}
static void _sounding_init(struct sounding_info *sounding)
{
    _rtw_memset(sounding->su_sounding_list, 0xFF, MAX_NUM_BEAMFORMEE_SU);
    _rtw_memset(sounding->mu_sounding_list, 0xFF, MAX_NUM_BEAMFORMEE_MU);
    sounding->state = SOUNDING_STATE_NONE;
    sounding->su_bfee_curidx = 0xFF;
    sounding->candidate_mu_bfee_cnt = 0;
    sounding->min_sounding_period = 0;
    sounding->sound_remain_cnt_per_period = 0;
}
static void _sounding_reset_vars(PADAPTER adapter)
{
    struct beamforming_info    *info;
    struct sounding_info *sounding;
    u8 idx;
    info = GET_BEAMFORM_INFO(adapter);
    sounding = &info->sounding_info;
    _rtw_memset(sounding->su_sounding_list, 0xFF, MAX_NUM_BEAMFORMEE_SU);
    _rtw_memset(sounding->mu_sounding_list, 0xFF, MAX_NUM_BEAMFORMEE_MU);
    sounding->su_bfee_curidx = 0xFF;
    sounding->candidate_mu_bfee_cnt = 0;
    /* Clear bSound flag for the new period */
    for (idx = 0; idx < MAX_BEAMFORMEE_ENTRY_NUM; idx++) {
        if ((info->bfee_entry[idx].used == _TRUE)
            && (info->bfee_entry[idx].sounding == _TRUE)) {
            info->bfee_entry[idx].sounding = _FALSE;
            info->bfee_entry[idx].bCandidateSoundingPeer = _FALSE;
        }
    }
}
/*
 * Return
 *    0    Prepare sounding list OK
 *    -1    Fail to prepare sounding list, because no beamformee need to souding
 *    -2    Fail to prepare sounding list, because beamformee state not ready
 *
 */
static int _sounding_get_list(PADAPTER adapter)
{
    struct beamforming_info    *info;
    struct sounding_info *sounding;
    struct beamformee_entry *bfee;
    u8 i, mu_idx = 0, su_idx = 0, not_ready = 0;
    int ret = 0;
    info = GET_BEAMFORM_INFO(adapter);
    sounding = &info->sounding_info;
    /* Add MU BFee list first because MU priority is higher than SU */
    for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
        bfee = &info->bfee_entry[i];
        if (bfee->used == _FALSE)
            continue;
        if (bfee->state != BEAMFORM_ENTRY_HW_STATE_ADDED) {
            RTW_ERR("%s: Invalid BFee idx(%d) Hw state=%d\n", __FUNCTION__, i, bfee->state);
            not_ready++;
            continue;
        }
        /*
         * Decrease BFee's SoundCnt per period
         * If the remain count is 0,
         * then it can be sounded at this time
         */
        if (bfee->SoundCnt) {
            bfee->SoundCnt--;
            if (bfee->SoundCnt)
                continue;
        }
        /*
         * <tynli_Note>
         *    If the STA supports MU BFee capability then we add it to MUSoundingList directly
         *    because we can only sound one STA by unicast NDPA with MU cap enabled to get correct channel info.
         *    Suggested by BB team Luke Lee. 2015.11.25.
         */
        if (bfee->cap & BEAMFORMEE_CAP_VHT_MU) {
            /* MU BFee */
            if (mu_idx >= MAX_NUM_BEAMFORMEE_MU) {
                RTW_ERR("%s: Too much MU bfee entry(Limit:%d)\n", __FUNCTION__, MAX_NUM_BEAMFORMEE_MU);
                continue;
            }
            if (bfee->bApplySounding == _TRUE) {
                bfee->bCandidateSoundingPeer = _TRUE;
                bfee->SoundCnt = GetInitSoundCnt(bfee->sound_period, sounding->min_sounding_period);
                sounding->mu_sounding_list[mu_idx] = i;
                mu_idx++;
            }
        } else if (bfee->cap & (BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT)) {
            /* SU BFee (HT/VHT) */
            if (su_idx >= MAX_NUM_BEAMFORMEE_SU) {
                RTW_ERR("%s: Too much SU bfee entry(Limit:%d)\n", __FUNCTION__, MAX_NUM_BEAMFORMEE_SU);
                continue;
            }
            if (bfee->bDeleteSounding == _TRUE) {
                sounding->su_sounding_list[su_idx] = i;
                su_idx++;
            } else if ((bfee->bApplySounding == _TRUE)
                && (bfee->bSuspendSUCap == _FALSE)) {
                bfee->bCandidateSoundingPeer = _TRUE;
                bfee->SoundCnt = GetInitSoundCnt(bfee->sound_period, sounding->min_sounding_period);
                sounding->su_sounding_list[su_idx] = i;
                su_idx++;
            }
        }
    }
    sounding->candidate_mu_bfee_cnt = mu_idx;
    if (su_idx + mu_idx == 0) {
        ret = -1;
        if (not_ready)
            ret = -2;
    }
    RTW_INFO("-%s: There are %d SU and %d MU BFees in this sounding period\n", __FUNCTION__, su_idx, mu_idx);
    return ret;
}
static void _sounding_handler(PADAPTER adapter)
{
    struct beamforming_info    *info;
    struct sounding_info *sounding;
    struct beamformee_entry *bfee;
    u8 su_idx, i;
    u32 timeout_period = 0;
    u8 set_timer = _FALSE;
    int ret = 0;
    static u16 wait_cnt = 0;
    info = GET_BEAMFORM_INFO(adapter);
    sounding = &info->sounding_info;
    RTW_DBG("+%s: state=%d\n", __FUNCTION__, sounding->state);
    if ((sounding->state != SOUNDING_STATE_INIT)
        && (sounding->state != SOUNDING_STATE_SU_SOUNDDOWN)
        && (sounding->state != SOUNDING_STATE_MU_SOUNDDOWN)
        && (sounding->state != SOUNDING_STATE_SOUNDING_TIMEOUT)) {
        RTW_WARN("%s: Invalid State(%d) and return!\n", __FUNCTION__, sounding->state);
        return;
    }
    if (sounding->state == SOUNDING_STATE_INIT) {
        RTW_INFO("%s: Sounding start\n", __FUNCTION__);
        /* Init Var */
        _sounding_reset_vars(adapter);
        /* Get the sounding list of this sounding period */
        ret = _sounding_get_list(adapter);
        if (ret == -1) {
            wait_cnt = 0;
            sounding->state = SOUNDING_STATE_NONE;
            RTW_ERR("%s: No BFees found, set to SOUNDING_STATE_NONE\n", __FUNCTION__);
            info->sounding_running--;
            return;
        }
        if (ret == -2) {
            RTW_WARN("%s: Temporarily cann't find BFee to sounding\n", __FUNCTION__);
            if (wait_cnt < 5) {
                wait_cnt++;
            } else {
                wait_cnt = 0;
                sounding->state = SOUNDING_STATE_NONE;
                RTW_ERR("%s: Wait changing state timeout!! Set to SOUNDING_STATE_NONE\n", __FUNCTION__);
            }
            info->sounding_running--;
            return;
        }
        if (ret != 0) {
            wait_cnt = 0;
            RTW_ERR("%s: Unkown state(%d)!\n", __FUNCTION__, ret);
            info->sounding_running--;
            return;
        }
        wait_cnt = 0;
        if (check_fwstate(&adapter->mlmepriv, WIFI_SITE_MONITOR) == _TRUE) {
            RTW_INFO("%s: Sounding abort! scanning APs...\n", __FUNCTION__);
            info->sounding_running--;
            return;
        }
        rtw_ps_deny(adapter, PS_DENY_BEAMFORMING);
        LeaveAllPowerSaveModeDirect(adapter);
    }
    /* Get non-sound SU BFee index */
    for (i = 0; i < MAX_NUM_BEAMFORMEE_SU; i++) {
        su_idx = sounding->su_sounding_list[i];
        if (su_idx >= MAX_BEAMFORMEE_ENTRY_NUM)
            continue;
        bfee = &info->bfee_entry[su_idx];
        if (_FALSE == bfee->sounding)
            break;
    }
    if (i < MAX_NUM_BEAMFORMEE_SU) {
        sounding->su_bfee_curidx = su_idx;
        /* Set to sounding start state */
        sounding->state = SOUNDING_STATE_SU_START;
        RTW_DBG("%s: Set to SOUNDING_STATE_SU_START\n", __FUNCTION__);
        bfee->sounding = _TRUE;
        /* Reset sounding timeout flag for the new sounding */
        bfee->bSoundingTimeout = _FALSE;
        if (_TRUE == bfee->bDeleteSounding) {
            u8 res = _FALSE;
            rtw_bf_cmd(adapter, BEAMFORMING_CTRL_END_PERIOD, &res, 1, 0);
            return;
        }
        /* Start SU sounding */
        if (bfee->cap & BEAMFORMEE_CAP_VHT_SU)
            _send_vht_ndpa_packet(adapter, bfee->mac_addr, bfee->aid, bfee->sound_bw);
        else if (bfee->cap & BEAMFORMEE_CAP_HT_EXPLICIT)
            _send_ht_ndpa_packet(adapter, bfee->mac_addr, bfee->sound_bw);
        /* Set sounding timeout timer */
        _set_timer(&info->sounding_timeout_timer, SU_SOUNDING_TIMEOUT);
        return;
    }
    if (sounding->candidate_mu_bfee_cnt > 0) {
        /*
         * If there is no SU BFee then find MU BFee and perform MU sounding
         *
         * <tynli_note> Need to check the MU starting condition. 2015.12.15.
         */
        sounding->state = SOUNDING_STATE_MU_START;
        RTW_DBG("%s: Set to SOUNDING_STATE_MU_START\n", __FUNCTION__);
        /* Update MU BFee info */
        for (i = 0; i < sounding->candidate_mu_bfee_cnt; i++) {
            bfee = &info->bfee_entry[sounding->mu_sounding_list[i]];
            bfee->sounding = _TRUE;
        }
        /* Send MU NDPA */
        bfee = &info->bfee_entry[sounding->mu_sounding_list[0]];
        _send_vht_mu_ndpa_packet(adapter, bfee->sound_bw);
        /* Send BF report poll if more than 1 MU STA */
        for (i = 1; i < sounding->candidate_mu_bfee_cnt; i++) {
            bfee = &info->bfee_entry[sounding->mu_sounding_list[i]];
            if (i == (sounding->candidate_mu_bfee_cnt - 1))/* The last STA*/
                _send_bf_report_poll(adapter, bfee->mac_addr, _TRUE);
            else
                _send_bf_report_poll(adapter, bfee->mac_addr, _FALSE);
        }
        sounding->candidate_mu_bfee_cnt = 0;
        /* Set sounding timeout timer */
        _set_timer(&info->sounding_timeout_timer, MU_SOUNDING_TIMEOUT);
        return;
    }
    info->sounding_running--;
    sounding->state = SOUNDING_STATE_INIT;
    RTW_INFO("%s: Sounding finished!\n", __FUNCTION__);
    rtw_ps_deny_cancel(adapter, PS_DENY_BEAMFORMING);
}
static void _sounding_force_stop(PADAPTER adapter)
{
    struct beamforming_info    *info;
    struct sounding_info *sounding;
    u8 cancelled;
    info = GET_BEAMFORM_INFO(adapter);
    sounding = &info->sounding_info;
    if ((sounding->state == SOUNDING_STATE_SU_START)
        || (sounding->state == SOUNDING_STATE_MU_START)) {
        u8 res = _FALSE;
        _cancel_timer(&info->sounding_timeout_timer, &cancelled);
        rtw_bf_cmd(adapter, BEAMFORMING_CTRL_END_PERIOD, &res, 1, 1);
        return;
    }
    info->sounding_running--;
    sounding->state = SOUNDING_STATE_INIT;
    RTW_INFO("%s: Sounding finished!\n", __FUNCTION__);
    rtw_ps_deny_cancel(adapter, PS_DENY_BEAMFORMING);
}
static void _sounding_timer_handler(void *FunctionContext)
{
    PADAPTER adapter;
    struct beamforming_info    *info;
    struct sounding_info *sounding;
    static u8 delay = 0;
    RTW_DBG("+%s\n", __FUNCTION__);
    adapter = (PADAPTER)FunctionContext;
    info = GET_BEAMFORM_INFO(adapter);
    sounding = &info->sounding_info;
    if (SOUNDING_STATE_NONE == sounding->state) {
        RTW_INFO("%s: Stop!\n", __FUNCTION__);
        if (info->sounding_running)
            RTW_WARN("%s: souding_running=%d when thread stop!\n",
                 __FUNCTION__, info->sounding_running);
        return;
    }
    _set_timer(&info->sounding_timer, sounding->min_sounding_period);
    if (!info->sounding_running) {
        if (SOUNDING_STATE_INIT != sounding->state) {
            RTW_WARN("%s: state(%d) != SOUNDING_STATE_INIT!!\n", __FUNCTION__, sounding->state);
            sounding->state = SOUNDING_STATE_INIT;
        }
        delay = 0;
        info->sounding_running++;
        rtw_bf_cmd(adapter, BEAMFORMING_CTRL_START_PERIOD, NULL, 0, 1);
    } else {
        if (delay != 0xFF)
            delay++;
        RTW_WARN("%s: souding is still processing...(state:%d, running:%d, delay:%d)\n",
             __FUNCTION__, sounding->state, info->sounding_running, delay);
        if (delay > 3) {
            RTW_WARN("%s: Stop sounding!!\n", __FUNCTION__);
            _sounding_force_stop(adapter);
        }
    }
}
static void _sounding_timeout_timer_handler(void *FunctionContext)
{
    PADAPTER adapter;
    struct beamforming_info    *info;
    struct sounding_info *sounding;
    struct beamformee_entry *bfee;
    RTW_WARN("+%s\n", __FUNCTION__);
    adapter = (PADAPTER)FunctionContext;
    info = GET_BEAMFORM_INFO(adapter);
    sounding = &info->sounding_info;
    if (SOUNDING_STATE_SU_START == sounding->state) {
        sounding->state = SOUNDING_STATE_SOUNDING_TIMEOUT;
        RTW_ERR("%s: Set to SU SOUNDING_STATE_SOUNDING_TIMEOUT\n", __FUNCTION__);
        /* SU BFee */
        bfee = &info->bfee_entry[sounding->su_bfee_curidx];
        bfee->bSoundingTimeout = _TRUE;
        RTW_WARN("%s: The BFee entry[%d] is Sounding Timeout!\n", __FUNCTION__, sounding->su_bfee_curidx);
    } else if (SOUNDING_STATE_MU_START == sounding->state) {
        sounding->state = SOUNDING_STATE_SOUNDING_TIMEOUT;
        RTW_ERR("%s: Set to MU SOUNDING_STATE_SOUNDING_TIMEOUT\n", __FUNCTION__);
    } else {
        RTW_WARN("%s: unexpected sounding state:0x%02x\n", __FUNCTION__, sounding->state);
        return;
    }
    rtw_bf_cmd(adapter, BEAMFORMING_CTRL_START_PERIOD, NULL, 0, 1);
}
static struct beamformer_entry *_bfer_get_free_entry(PADAPTER adapter)
{
    u8 i = 0;
    struct beamforming_info *info;
    struct beamformer_entry *bfer;
    info = GET_BEAMFORM_INFO(adapter);
    for (i = 0; i < MAX_BEAMFORMER_ENTRY_NUM; i++) {
        bfer = &info->bfer_entry[i];
        if (bfer->used == _FALSE)
            return bfer;
    }
    return NULL;
}
static struct beamformer_entry *_bfer_get_entry_by_addr(PADAPTER adapter, u8 *ra)
{
    u8 i = 0;
    struct beamforming_info *info;
    struct beamformer_entry *bfer;
    info = GET_BEAMFORM_INFO(adapter);
    for (i = 0; i < MAX_BEAMFORMER_ENTRY_NUM; i++) {
        bfer = &info->bfer_entry[i];
        if (bfer->used == _FALSE)
            continue;
        if (_rtw_memcmp(ra, bfer->mac_addr, ETH_ALEN) == _TRUE)
            return bfer;
    }
    return NULL;
}
static struct beamformer_entry *_bfer_add_entry(PADAPTER adapter,
    struct sta_info *sta, u8 bf_cap, u8 sounding_dim, u8 comp_steering)
{
    struct mlme_priv *mlme;
    struct beamforming_info *info;
    struct beamformer_entry *bfer;
    u8 *bssid;
    u16 val16;
    u8 i;
    mlme = &adapter->mlmepriv;
    info = GET_BEAMFORM_INFO(adapter);
    bfer = _bfer_get_entry_by_addr(adapter, sta->hwaddr);
    if (!bfer) {
        bfer = _bfer_get_free_entry(adapter);
        if (!bfer)
            return NULL;
    }
    bfer->used = _TRUE;
    _get_txvector_parameter(adapter, sta, &bfer->g_id, &bfer->p_aid);
    _rtw_memcpy(bfer->mac_addr, sta->hwaddr, ETH_ALEN);
    bfer->cap = bf_cap;
    bfer->state = BEAMFORM_ENTRY_HW_STATE_ADD_INIT;
    bfer->NumofSoundingDim = sounding_dim;
    if (TEST_FLAG(bf_cap, BEAMFORMER_CAP_VHT_MU)) {
        info->beamformer_mu_cnt += 1;
        bfer->aid = sta->aid;
    } else if (TEST_FLAG(bf_cap, BEAMFORMER_CAP_VHT_SU|BEAMFORMER_CAP_HT_EXPLICIT)) {
        info->beamformer_su_cnt += 1;
        /* Record HW idx info */
        for (i = 0; i < MAX_NUM_BEAMFORMER_SU; i++) {
            if ((info->beamformer_su_reg_maping & BIT(i)) == 0) {
                info->beamformer_su_reg_maping |= BIT(i);
                bfer->su_reg_index = i;
                break;
            }
        }
        RTW_INFO("%s: Add BFer entry beamformer_su_reg_maping=%#x, su_reg_index=%d\n",
             __FUNCTION__, info->beamformer_su_reg_maping, bfer->su_reg_index);
    }
    return bfer;
}
static void _bfer_remove_entry(PADAPTER adapter, struct beamformer_entry *entry)
{
    struct beamforming_info *info;
    info = GET_BEAMFORM_INFO(adapter);
    entry->state = BEAMFORM_ENTRY_HW_STATE_DELETE_INIT;
    if (TEST_FLAG(entry->cap, BEAMFORMER_CAP_VHT_MU)) {
        info->beamformer_mu_cnt -= 1;
        _rtw_memset(entry->gid_valid, 0, 8);
        _rtw_memset(entry->user_position, 0, 16);
    } else if (TEST_FLAG(entry->cap, BEAMFORMER_CAP_VHT_SU|BEAMFORMER_CAP_HT_EXPLICIT)) {
        info->beamformer_su_cnt -= 1;
    }
    if (info->beamformer_mu_cnt == 0)
        info->beamforming_cap &= ~BEAMFORMEE_CAP_VHT_MU;
    if (info->beamformer_su_cnt == 0)
        info->beamforming_cap &= ~(BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT);
}
static u8 _bfer_set_entry_gid(PADAPTER adapter, u8 *addr, u8 *gid, u8 *position)
{
    struct beamformer_entry *bfer = NULL;
    bfer = _bfer_get_entry_by_addr(adapter, addr);
    if (!bfer) {
        RTW_INFO("%s: Cannot find BFer entry!!\n", __FUNCTION__);
        return _FAIL;
    }
    /* Parsing Membership Status Array */
    _rtw_memcpy(bfer->gid_valid, gid, 8);
    /* Parsing User Position Array */
    _rtw_memcpy(bfer->user_position, position, 16);
    /* Config HW GID table */
    rtw_bf_cmd(adapter, BEAMFORMING_CTRL_SET_GID_TABLE, (u8*)&bfer, sizeof(struct beamformer_entry *), 1);
    return _SUCCESS;
}
static struct beamformee_entry *_bfee_get_free_entry(PADAPTER adapter)
{
    u8 i = 0;
    struct beamforming_info *info;
    struct beamformee_entry *bfee;
    info = GET_BEAMFORM_INFO(adapter);
    for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
        bfee = &info->bfee_entry[i];
        if (bfee->used == _FALSE)
            return bfee;
    }
    return NULL;
}
static struct beamformee_entry *_bfee_get_entry_by_addr(PADAPTER adapter, u8 *ra)
{
    u8 i = 0;
    struct beamforming_info *info;
    struct beamformee_entry *bfee;
    info = GET_BEAMFORM_INFO(adapter);
    for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
        bfee = &info->bfee_entry[i];
        if (bfee->used == _FALSE)
            continue;
        if (_rtw_memcmp(ra, bfee->mac_addr, ETH_ALEN) == _TRUE)
            return bfee;
    }
    return NULL;
}
static u8 _bfee_get_first_su_entry_idx(PADAPTER adapter, struct beamformee_entry *ignore)
{
    struct beamforming_info *info;
    struct beamformee_entry *bfee;
    u8 i;
    info = GET_BEAMFORM_INFO(adapter);
    for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
        bfee = &info->bfee_entry[i];
        if (ignore && (bfee == ignore))
            continue;
        if (bfee->used == _FALSE)
            continue;
        if ((!TEST_FLAG(bfee->cap, BEAMFORMEE_CAP_VHT_MU))
            && TEST_FLAG(bfee->cap, BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT))
            return i;
    }
    return 0xFF;
}
/*
 * Description:
 *    Get the first entry index of MU Beamformee.
 *
 * Return Value:
 *    Index of the first MU sta, or 0xFF for invalid index.
 *
 * 2015.05.25. Created by tynli.
 *
 */
static u8 _bfee_get_first_mu_entry_idx(PADAPTER adapter, struct beamformee_entry *ignore)
{
    struct beamforming_info *info;
    struct beamformee_entry *bfee;
    u8 i;
    info = GET_BEAMFORM_INFO(adapter);
    for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
        bfee = &info->bfee_entry[i];
        if (ignore && (bfee == ignore))
            continue;
        if (bfee->used == _FALSE)
            continue;
        if (TEST_FLAG(bfee->cap, BEAMFORMEE_CAP_VHT_MU))
            return i;
    }
    return 0xFF;
}
static struct beamformee_entry *_bfee_add_entry(PADAPTER adapter,
    struct sta_info *sta, u8 bf_cap, u8 sounding_dim, u8 comp_steering)
{
    struct mlme_priv *mlme;
    struct beamforming_info *info;
    struct beamformee_entry *bfee;
    u8 *bssid;
    u16 val16;
    u8 i;
    mlme = &adapter->mlmepriv;
    info = GET_BEAMFORM_INFO(adapter);
    bfee = _bfee_get_entry_by_addr(adapter, sta->hwaddr);
    if (!bfee) {
        bfee = _bfee_get_free_entry(adapter);
        if (!bfee)
            return NULL;
    }
    bfee->used = _TRUE;
    bfee->aid = sta->aid;
    bfee->mac_id = sta->mac_id;
    bfee->sound_bw = sta->bw_mode;
    _get_txvector_parameter(adapter, sta, &bfee->g_id, &bfee->p_aid);
    sta->txbf_gid = bfee->g_id;
    sta->txbf_paid = bfee->p_aid;
    _rtw_memcpy(bfee->mac_addr, sta->hwaddr, ETH_ALEN);
    bfee->txbf = _FALSE;
    bfee->sounding = _FALSE;
    bfee->sound_period = 40;
    _sounding_update_min_period(adapter, bfee->sound_period, _FALSE);
    bfee->SoundCnt = GetInitSoundCnt(bfee->sound_period, info->sounding_info.min_sounding_period);
    bfee->cap = bf_cap;
    bfee->state = BEAMFORM_ENTRY_HW_STATE_ADD_INIT;
    bfee->bCandidateSoundingPeer = _FALSE;
    bfee->bSoundingTimeout = _FALSE;
    bfee->bDeleteSounding = _FALSE;
    bfee->bApplySounding = _TRUE;
    bfee->tx_timestamp = 0;
    bfee->tx_bytes = 0;
    bfee->LogStatusFailCnt = 0;
    bfee->NumofSoundingDim = sounding_dim;
    bfee->comp_steering_num_of_bfer = comp_steering;
    bfee->bSuspendSUCap = _FALSE;
    if (TEST_FLAG(bf_cap, BEAMFORMEE_CAP_VHT_MU)) {
        info->beamformee_mu_cnt += 1;
        info->first_mu_bfee_index = _bfee_get_first_mu_entry_idx(adapter, NULL);
        if (_TRUE == info->bEnableSUTxBFWorkAround) {
            /* When the first MU BFee added, discard SU BFee bfee's capability */
            if ((info->beamformee_mu_cnt == 1) && (info->beamformee_su_cnt > 0)) {
                if (info->TargetSUBFee) {
                    info->TargetSUBFee->bSuspendSUCap = _TRUE;
                    info->TargetSUBFee->bDeleteSounding = _TRUE;
                } else {
                    RTW_ERR("%s: UNEXPECTED!! info->TargetSUBFee is NULL!", __FUNCTION__);
                }
                info->TargetSUBFee = NULL;
                _rtw_memset(&info->TargetCSIInfo, 0, sizeof(struct _RT_CSI_INFO));
                rtw_bf_cmd(adapter, BEAMFORMING_CTRL_SET_CSI_REPORT, (u8*)&info->TargetCSIInfo, sizeof(struct _RT_CSI_INFO), 0);
            }
        }
        /* Record HW idx info */
        for (i = 0; i < MAX_NUM_BEAMFORMEE_MU; i++) {
            if ((info->beamformee_mu_reg_maping & BIT(i)) == 0) {
                info->beamformee_mu_reg_maping |= BIT(i);
                bfee->mu_reg_index = i;
                break;
            }
        }
        RTW_INFO("%s: Add BFee entry beamformee_mu_reg_maping=%#x, mu_reg_index=%d\n",
             __FUNCTION__, info->beamformee_mu_reg_maping, bfee->mu_reg_index);
    } else if (TEST_FLAG(bf_cap, BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT)) {
        info->beamformee_su_cnt += 1;
        if (_TRUE == info->bEnableSUTxBFWorkAround) {
            /* Record the first SU BFee index. We only allow the first SU BFee to be sound */
            if ((info->beamformee_su_cnt == 1) && (info->beamformee_mu_cnt == 0)) {
                info->TargetSUBFee = bfee;
                _rtw_memset(&info->TargetCSIInfo, 0, sizeof(struct _RT_CSI_INFO));
                bfee->bSuspendSUCap = _FALSE;
            } else {
                bfee->bSuspendSUCap = _TRUE;
            }
        }
        /* Record HW idx info */
        for (i = 0; i < MAX_NUM_BEAMFORMEE_SU; i++) {
            if ((info->beamformee_su_reg_maping & BIT(i)) == 0) {
                info->beamformee_su_reg_maping |= BIT(i);
                bfee->su_reg_index = i;
                break;
            }
        }
        RTW_INFO("%s: Add BFee entry beamformee_su_reg_maping=%#x, su_reg_index=%d\n",
             __FUNCTION__, info->beamformee_su_reg_maping, bfee->su_reg_index);
    }
    return bfee;
}
static void _bfee_remove_entry(PADAPTER adapter, struct beamformee_entry *entry)
{
    struct beamforming_info *info;
    u8 idx;
    info = GET_BEAMFORM_INFO(adapter);
    entry->state = BEAMFORM_ENTRY_HW_STATE_DELETE_INIT;
    if (TEST_FLAG(entry->cap, BEAMFORMEE_CAP_VHT_MU)) {
        info->beamformee_mu_cnt -= 1;
        info->first_mu_bfee_index = _bfee_get_first_mu_entry_idx(adapter, entry);
        if (_TRUE == info->bEnableSUTxBFWorkAround) {
            if ((info->beamformee_mu_cnt == 0) && (info->beamformee_su_cnt > 0)) {
                idx = _bfee_get_first_su_entry_idx(adapter, NULL);
                info->TargetSUBFee = &info->bfee_entry[idx];
                _rtw_memset(&info->TargetCSIInfo, 0, sizeof(struct _RT_CSI_INFO));
                info->TargetSUBFee->bSuspendSUCap = _FALSE;
            }
        }
    } else if (TEST_FLAG(entry->cap, BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT)) {
        info->beamformee_su_cnt -= 1;
        /* When the target SU BFee leaves, disable workaround */
        if ((_TRUE == info->bEnableSUTxBFWorkAround)
            && (entry == info->TargetSUBFee)) {
            entry->bSuspendSUCap = _TRUE;
            info->TargetSUBFee = NULL;
            _rtw_memset(&info->TargetCSIInfo, 0, sizeof(struct _RT_CSI_INFO));
            rtw_bf_cmd(adapter, BEAMFORMING_CTRL_SET_CSI_REPORT, (u8*)&info->TargetCSIInfo, sizeof(struct _RT_CSI_INFO), 0);
        }
    }
    if (info->beamformee_mu_cnt == 0)
        info->beamforming_cap &= ~BEAMFORMER_CAP_VHT_MU;
    if (info->beamformee_su_cnt == 0)
        info->beamforming_cap &= ~(BEAMFORMER_CAP_VHT_SU|BEAMFORMER_CAP_HT_EXPLICIT);
    _sounding_update_min_period(adapter, 0, _TRUE);
}
static enum beamforming_cap _bfee_get_entry_cap_by_macid(PADAPTER adapter, u8 macid)
{
    struct beamforming_info *info;
    struct beamformee_entry *bfee;
    u8 i;
    info = GET_BEAMFORM_INFO(adapter);
    for (i = 0; i < MAX_BEAMFORMER_ENTRY_NUM; i++) {
        bfee = &info->bfee_entry[i];
        if (bfee->used == _FALSE)
            continue;
        if (bfee->mac_id == macid)
            return bfee->cap;
    }
    return BEAMFORMING_CAP_NONE;
}
static void _beamforming_enter(PADAPTER adapter, void *p)
{
    struct mlme_priv *mlme;
    struct ht_priv *htpriv;
#ifdef CONFIG_80211AC_VHT
    struct vht_priv *vhtpriv;
#endif
    struct mlme_ext_priv *mlme_ext;
    struct sta_info *sta, *sta_copy;
    struct beamforming_info *info;
    struct beamformer_entry *bfer = NULL;
    struct beamformee_entry *bfee = NULL;
    u8 wireless_mode;
    u8 sta_bf_cap;
    u8 sounding_dim = 0; /* number of sounding dimensions */
    u8 comp_steering_num = 0; /* compressed steering number */
    mlme = &adapter->mlmepriv;
    htpriv = &mlme->htpriv;
#ifdef CONFIG_80211AC_VHT
    vhtpriv = &mlme->vhtpriv;
#endif
    mlme_ext = &adapter->mlmeextpriv;
    info = GET_BEAMFORM_INFO(adapter);
    sta_copy = (struct sta_info *)p;
    sta = rtw_get_stainfo(&adapter->stapriv, sta_copy->hwaddr);
    if (!sta) {
        RTW_ERR("%s: Cann't find STA info for " MAC_FMT "\n",
                __FUNCTION__, MAC_ARG(sta_copy->hwaddr));
        return;
    }
    if (sta != sta_copy) {
        RTW_WARN("%s: Origin sta(fake)=%p realsta=%p for " MAC_FMT "\n",
                 __FUNCTION__, sta_copy, sta, MAC_ARG(sta_copy->hwaddr));
    }
    /* The current setting does not support Beaforming */
    wireless_mode = sta->wireless_mode;
    if ((is_supported_ht(wireless_mode) == _FALSE)
        && (is_supported_vht(wireless_mode) == _FALSE)) {
        RTW_WARN("%s: Not support HT or VHT mode\n", __FUNCTION__);
        return;
    }
    if ((0 == htpriv->beamform_cap)
#ifdef CONFIG_80211AC_VHT
        && (0 == vhtpriv->beamform_cap)
#endif
       ) {
        RTW_INFO("The configuration disabled Beamforming! Skip...\n");
        return;
    }
    _get_sta_beamform_cap(adapter, sta,
                  &sta_bf_cap, &sounding_dim, &comp_steering_num);
    RTW_INFO("STA Beamforming Capability=0x%02X\n", sta_bf_cap);
    if (sta_bf_cap == BEAMFORMING_CAP_NONE)
        return;
    if ((sta_bf_cap & BEAMFORMEE_CAP_HT_EXPLICIT)
        || (sta_bf_cap & BEAMFORMEE_CAP_VHT_SU)
        || (sta_bf_cap & BEAMFORMEE_CAP_VHT_MU))
        sta_bf_cap |= BEAMFORMEE_CAP;
    if ((sta_bf_cap & BEAMFORMER_CAP_HT_EXPLICIT)
        || (sta_bf_cap & BEAMFORMER_CAP_VHT_SU)
        || (sta_bf_cap & BEAMFORMER_CAP_VHT_MU))
        sta_bf_cap |= BEAMFORMER_CAP;
    if (sta_bf_cap & BEAMFORMER_CAP) {
        /* The other side is beamformer */
        bfer = _bfer_add_entry(adapter, sta, sta_bf_cap, sounding_dim, comp_steering_num);
        if (!bfer)
            RTW_ERR("%s: Fail to allocate bfer entry!\n", __FUNCTION__);
    }
    if (sta_bf_cap & BEAMFORMEE_CAP) {
        /* The other side is beamformee */
        bfee = _bfee_add_entry(adapter, sta, sta_bf_cap, sounding_dim, comp_steering_num);
        if (!bfee)
            RTW_ERR("%s: Fail to allocate bfee entry!\n", __FUNCTION__);
    }
    if (!bfer && !bfee)
        return;
    rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_ENTER, (u8*)sta);
    /* Perform sounding if there is BFee */
    if ((info->beamformee_su_cnt != 0)
        || (info->beamformee_mu_cnt != 0)) {
        if (SOUNDING_STATE_NONE == info->sounding_info.state) {
            info->sounding_info.state = SOUNDING_STATE_INIT;
            /* Start sounding after 2 sec */
            _set_timer(&info->sounding_timer, 2000);
        }
    }
}
static void _beamforming_reset(PADAPTER adapter)
{
    RTW_ERR("%s: Not ready!!\n", __FUNCTION__);
}
static void _beamforming_leave(PADAPTER adapter, u8 *ra)
{
    struct beamforming_info *info;
    struct beamformer_entry *bfer = NULL;
    struct beamformee_entry *bfee = NULL;
    u8 bHwStateAddInit = _FALSE;
    RTW_INFO("+%s\n", __FUNCTION__);
    info = GET_BEAMFORM_INFO(adapter);
    bfer = _bfer_get_entry_by_addr(adapter, ra);
    bfee = _bfee_get_entry_by_addr(adapter, ra);
    if (!bfer && !bfee) {
        RTW_WARN("%s: " MAC_FMT " is neither beamforming ee or er!!\n",
            __FUNCTION__, MAC_ARG(ra));
        return;
    }
    if (bfer)
        _bfer_remove_entry(adapter, bfer);
    if (bfee)
        _bfee_remove_entry(adapter, bfee);
    rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_LEAVE, ra);
    /* Stop sounding if there is no any BFee */
    if ((info->beamformee_su_cnt == 0)
        && (info->beamformee_mu_cnt == 0)) {
        u8 cancelled;
        _cancel_timer(&info->sounding_timer, &cancelled);
        _sounding_init(&info->sounding_info);
    }
    RTW_INFO("-%s\n", __FUNCTION__);
}
static void _beamforming_sounding_down(PADAPTER adapter, u8 status)
{
    struct beamforming_info    *info;
    struct sounding_info *sounding;
    struct beamformee_entry *bfee;
    info = GET_BEAMFORM_INFO(adapter);
    sounding = &info->sounding_info;
    RTW_INFO("+%s: sounding=%d, status=0x%02x\n", __FUNCTION__, sounding->state, status);
    if (sounding->state == SOUNDING_STATE_MU_START) {
        RTW_INFO("%s: MU sounding done\n", __FUNCTION__);
        sounding->state = SOUNDING_STATE_MU_SOUNDDOWN;
        RTW_INFO("%s: Set to SOUNDING_STATE_MU_SOUNDDOWN\n", __FUNCTION__);
        info->SetHalSoundownOnDemandCnt++;
        rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_STATUS, &status);
    } else if (sounding->state == SOUNDING_STATE_SU_START) {
        RTW_INFO("%s: SU entry[%d] sounding down\n", __FUNCTION__, sounding->su_bfee_curidx);
        bfee = &info->bfee_entry[sounding->su_bfee_curidx];
        sounding->state = SOUNDING_STATE_SU_SOUNDDOWN;
        RTW_INFO("%s: Set to SOUNDING_STATE_SU_SOUNDDOWN\n", __FUNCTION__);
        /*
         * <tynli_note>
         *    bfee->bSoundingTimeout this flag still cannot avoid
         *    old sound down event happens in the new sounding period.
         *    2015.12.10
         */
        if (_TRUE == bfee->bSoundingTimeout) {
            RTW_WARN("%s: The entry[%d] is bSoundingTimeout!\n", __FUNCTION__, sounding->su_bfee_curidx);
            bfee->bSoundingTimeout = _FALSE;
            return;
        }
        if (_TRUE == status) {
            /* success */
            bfee->LogStatusFailCnt = 0;
            info->SetHalSoundownOnDemandCnt++;
            rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_STATUS, &status);
        } else if (_TRUE == bfee->bDeleteSounding) {
            RTW_WARN("%s: Delete entry[%d] sounding info!\n", __FUNCTION__, sounding->su_bfee_curidx);
            rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_STATUS, &status);
            bfee->bDeleteSounding = _FALSE;
        } else {
            bfee->LogStatusFailCnt++;
            RTW_WARN("%s: LogStatusFailCnt=%d\n", __FUNCTION__, bfee->LogStatusFailCnt);
            if (bfee->LogStatusFailCnt > 30) {
                RTW_ERR("%s: LogStatusFailCnt > 30, Stop SOUNDING!!\n", __FUNCTION__);
                rtw_bf_cmd(adapter, BEAMFORMING_CTRL_LEAVE, bfee->mac_addr, ETH_ALEN, 1);
            }
        }
    } else {
        RTW_WARN("%s: unexpected sounding state:0x%02x\n", __FUNCTION__, sounding->state);
        return;
    }
    rtw_bf_cmd(adapter, BEAMFORMING_CTRL_START_PERIOD, NULL, 0, 0);
}
static void _c2h_snd_txbf(PADAPTER adapter, u8 *buf, u8 buf_len)
{
    struct beamforming_info    *info;
    u8 cancelled;
    u8 res;
    info = GET_BEAMFORM_INFO(adapter);
    _cancel_timer(&info->sounding_timeout_timer, &cancelled);
    res = C2H_SND_TXBF_GET_SND_RESULT(buf) ? _TRUE : _FALSE;
    RTW_INFO("+%s: %s\n", __FUNCTION__, res==_TRUE?"Success":"Fail!");
    rtw_bf_cmd(adapter, BEAMFORMING_CTRL_END_PERIOD, &res, 1, 1);
}
/*
 * Description:
 *    This function is for phydm only
 */
enum beamforming_cap rtw_bf_bfee_get_entry_cap_by_macid(void *mlme, u8 macid)
{
    PADAPTER adapter;
    enum beamforming_cap cap = BEAMFORMING_CAP_NONE;
    adapter = mlme_to_adapter((struct mlme_priv *)mlme);
    cap = _bfee_get_entry_cap_by_macid(adapter, macid);
    return cap;
}
struct beamformer_entry *rtw_bf_bfer_get_entry_by_addr(PADAPTER adapter, u8 *ra)
{
    return _bfer_get_entry_by_addr(adapter, ra);
}
struct beamformee_entry *rtw_bf_bfee_get_entry_by_addr(PADAPTER adapter, u8 *ra)
{
    return _bfee_get_entry_by_addr(adapter, ra);
}
void rtw_bf_get_ndpa_packet(PADAPTER adapter, union recv_frame *precv_frame)
{
    RTW_DBG("+%s\n", __FUNCTION__);
}
u32 rtw_bf_get_report_packet(PADAPTER adapter, union recv_frame *precv_frame)
{
    u32 ret = _SUCCESS;
    struct beamforming_info *info;
    struct beamformee_entry *bfee = NULL;
    u8 *pframe;
    u32 frame_len;
    u8 *ta;
    u8 *frame_body;
    u8 category, action;
    u8 *pMIMOCtrlField, *pCSIMatrix;
    u8 Nc = 0, Nr = 0, CH_W = 0, Ng = 0, CodeBook = 0;
    u16 CSIMatrixLen = 0;
    RTW_INFO("+%s\n", __FUNCTION__);
    info = GET_BEAMFORM_INFO(adapter);
    pframe = precv_frame->u.hdr.rx_data;
    frame_len = precv_frame->u.hdr.len;
    /* Memory comparison to see if CSI report is the same with previous one */
    ta = get_addr2_ptr(pframe);
    bfee = _bfee_get_entry_by_addr(adapter, ta);
    if (!bfee)
        return _FAIL;
    frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
    category = frame_body[0];
    action = frame_body[1];
    if ((category == RTW_WLAN_CATEGORY_VHT)
        && (action == RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING)) {
        pMIMOCtrlField = pframe + 26;
        Nc = (*pMIMOCtrlField) & 0x7;
        Nr = ((*pMIMOCtrlField) & 0x38) >> 3;
        CH_W =  (((*pMIMOCtrlField) & 0xC0) >> 6);
        Ng = (*(pMIMOCtrlField+1)) & 0x3;
        CodeBook = ((*(pMIMOCtrlField+1)) & 0x4) >> 2;
        /*
         * 24+(1+1+3)+2
         * ==> MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)
         */
        pCSIMatrix = pMIMOCtrlField + 3 + Nc;
        CSIMatrixLen = frame_len - 26 - 3 - Nc;
        info->TargetCSIInfo.bVHT = _TRUE;
    } else if ((category == RTW_WLAN_CATEGORY_HT)
           && (action == RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING)) {
        pMIMOCtrlField = pframe + 26;
        Nc = (*pMIMOCtrlField) & 0x3;
        Nr = ((*pMIMOCtrlField) & 0xC) >> 2;
        CH_W = ((*pMIMOCtrlField) & 0x10) >> 4;
        Ng = ((*pMIMOCtrlField) & 0x60) >> 5;
        CodeBook = ((*(pMIMOCtrlField+1)) & 0x6) >> 1;
        /*
         * 24+(1+1+6)+2
         * ==> MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)
         */
        pCSIMatrix = pMIMOCtrlField + 6 + Nr;
        CSIMatrixLen = frame_len  - 26 - 6 - Nr;
        info->TargetCSIInfo.bVHT = _FALSE;
    }
    /* Update current CSI report info */
    if ((_TRUE == info->bEnableSUTxBFWorkAround)
        && (info->TargetSUBFee == bfee)) {
        if ((info->TargetCSIInfo.Nc != Nc) || (info->TargetCSIInfo.Nr != Nr) ||
            (info->TargetCSIInfo.ChnlWidth != CH_W) || (info->TargetCSIInfo.Ng != Ng) ||
            (info->TargetCSIInfo.CodeBook != CodeBook)) {
            info->TargetCSIInfo.Nc = Nc;
            info->TargetCSIInfo.Nr = Nr;
            info->TargetCSIInfo.ChnlWidth = CH_W;
            info->TargetCSIInfo.Ng = Ng;
            info->TargetCSIInfo.CodeBook = CodeBook;
            rtw_bf_cmd(adapter, BEAMFORMING_CTRL_SET_CSI_REPORT, (u8*)&info->TargetCSIInfo, sizeof(struct _RT_CSI_INFO), 1);
        }
    }
    RTW_INFO("%s: pkt type=%d-%d, Nc=%d, Nr=%d, CH_W=%d, Ng=%d, CodeBook=%d\n",
         __FUNCTION__, category, action, Nc, Nr, CH_W, Ng, CodeBook);
    return ret;
}
u8 rtw_bf_send_vht_gid_mgnt_packet(PADAPTER adapter, u8 *ra, u8 *gid, u8 *position)
{
    /* General */
    struct xmit_priv *xmitpriv;
    struct mlme_priv *mlmepriv;
    struct xmit_frame *pmgntframe;
    /* MISC */
    struct pkt_attrib *attrib;
    struct rtw_ieee80211_hdr *wlanhdr;
    u8 *pframe, *ptr;
    xmitpriv = &adapter->xmitpriv;
    mlmepriv = &adapter->mlmepriv;
    pmgntframe = alloc_mgtxmitframe(xmitpriv);
    if (!pmgntframe)
        return _FALSE;
    /* update attribute */
    attrib = &pmgntframe->attrib;
    update_mgntframe_attrib(adapter, attrib);
    attrib->rate = MGN_6M;
    attrib->bwmode = CHANNEL_WIDTH_20;
    attrib->subtype = WIFI_ACTION;
    _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
    pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
    wlanhdr = (struct rtw_ieee80211_hdr *)pframe;
    wlanhdr->frame_ctl = 0;
    set_frame_sub_type(pframe, attrib->subtype);
    set_duration(pframe, 0);
    SetFragNum(pframe, 0);
    SetSeqNum(pframe, 0);
    _rtw_memcpy(wlanhdr->addr1, ra, ETH_ALEN);
    _rtw_memcpy(wlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
    _rtw_memcpy(wlanhdr->addr3, get_bssid(mlmepriv), ETH_ALEN);
    pframe[24] = RTW_WLAN_CATEGORY_VHT;
    pframe[25] = RTW_WLAN_ACTION_VHT_GROUPID_MANAGEMENT;
    /* Set Membership Status Array */
    ptr = pframe + 26;
    _rtw_memcpy(ptr, gid, 8);
    /* Set User Position Array */
    ptr = pframe + 34;
    _rtw_memcpy(ptr, position, 16);
    attrib->pktlen = 54;
    attrib->last_txcmdsz = attrib->pktlen;
    dump_mgntframe(adapter, pmgntframe);
    return _TRUE;
}
/*
 * Description:
 *    On VHT GID management frame by an MU beamformee.
 */
void rtw_bf_get_vht_gid_mgnt_packet(PADAPTER adapter, union recv_frame *precv_frame)
{
    u8 *pframe;
    u8 *ta, *gid, *position;
    RTW_DBG("+%s\n", __FUNCTION__);
    pframe = precv_frame->u.hdr.rx_data;
    /* Get address by Addr2 */
    ta = get_addr2_ptr(pframe);
    /* Remove signaling TA */
    ta[0] &= 0xFE;
    /* Membership Status Array */
    gid = pframe + 26;
    /* User Position Array */
    position= pframe + 34;
    _bfer_set_entry_gid(adapter, ta, gid, position);
}
void rtw_bf_init(PADAPTER adapter)
{
    struct beamforming_info    *info;
    info = GET_BEAMFORM_INFO(adapter);
    info->beamforming_cap = BEAMFORMING_CAP_NONE;
    info->beamforming_state = BEAMFORMING_STATE_IDLE;
/*
    info->bfee_entry[MAX_BEAMFORMEE_ENTRY_NUM];
    info->bfer_entry[MAX_BEAMFORMER_ENTRY_NUM];
*/
    info->sounding_sequence = 0;
    info->beamformee_su_cnt = 0;
    info->beamformer_su_cnt = 0;
    info->beamformee_su_reg_maping = 0;
    info->beamformer_su_reg_maping = 0;
    info->beamformee_mu_cnt = 0;
    info->beamformer_mu_cnt = 0;
    info->beamformee_mu_reg_maping = 0;
    info->first_mu_bfee_index = 0xFF;
    info->mu_bfer_curidx = 0xFF;
    _sounding_init(&info->sounding_info);
    _init_timer(&info->sounding_timer, adapter->pnetdev, _sounding_timer_handler, adapter);
    _init_timer(&info->sounding_timeout_timer, adapter->pnetdev, _sounding_timeout_timer_handler, adapter);
    info->SetHalBFEnterOnDemandCnt = 0;
    info->SetHalBFLeaveOnDemandCnt = 0;
    info->SetHalSoundownOnDemandCnt = 0;
    info->bEnableSUTxBFWorkAround = _TRUE;
    info->TargetSUBFee = NULL;
    info->sounding_running = 0;
}
void rtw_bf_cmd_hdl(PADAPTER adapter, u8 type, u8 *pbuf)
{
    switch (type) {
    case BEAMFORMING_CTRL_ENTER:
        _beamforming_enter(adapter, pbuf);
        break;
    case BEAMFORMING_CTRL_LEAVE:
        if (pbuf == NULL)
            _beamforming_reset(adapter);
        else
            _beamforming_leave(adapter, pbuf);
        break;
    case BEAMFORMING_CTRL_START_PERIOD:
        _sounding_handler(adapter);
        break;
    case BEAMFORMING_CTRL_END_PERIOD:
        _beamforming_sounding_down(adapter, *pbuf);
        break;
    case BEAMFORMING_CTRL_SET_GID_TABLE:
        rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_SET_GID_TABLE, *(void**)pbuf);
        break;
    case BEAMFORMING_CTRL_SET_CSI_REPORT:
        rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_CSI_REPORT, pbuf);
        break;
    default:
        break;
    }
}
u8 rtw_bf_cmd(PADAPTER adapter, s32 type, u8 *pbuf, s32 size, u8 enqueue)
{
    struct cmd_obj *ph2c;
    struct drvextra_cmd_parm *pdrvextra_cmd_parm;
    struct cmd_priv    *pcmdpriv = &adapter->cmdpriv;
    u8 *wk_buf;
    u8 res = _SUCCESS;
    if (!enqueue) {
        rtw_bf_cmd_hdl(adapter, type, pbuf);
        goto exit;
    }
    ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
    if (ph2c == NULL) {
        res = _FAIL;
        goto exit;
    }
    pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
    if (pdrvextra_cmd_parm == NULL) {
        rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
        res = _FAIL;
        goto exit;
    }
    if (pbuf != NULL) {
        wk_buf = rtw_zmalloc(size);
        if (wk_buf == NULL) {
            rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
            rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
            res = _FAIL;
            goto exit;
        }
        _rtw_memcpy(wk_buf, pbuf, size);
    } else {
        wk_buf = NULL;
        size = 0;
    }
    pdrvextra_cmd_parm->ec_id = BEAMFORMING_WK_CID;
    pdrvextra_cmd_parm->type = type;
    pdrvextra_cmd_parm->size = size;
    pdrvextra_cmd_parm->pbuf = wk_buf;
    init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
    res = rtw_enqueue_cmd(pcmdpriv, ph2c);
exit:
    return res;
}
void rtw_bf_update_attrib(PADAPTER adapter, struct pkt_attrib *attrib, struct sta_info *sta)
{
    if (sta) {
        attrib->txbf_g_id = sta->txbf_gid;
        attrib->txbf_p_aid = sta->txbf_paid;
    }
}
void rtw_bf_c2h_handler(PADAPTER adapter, u8 id, u8 *buf, u8 buf_len)
{
    switch (id) {
    case CMD_ID_C2H_SND_TXBF:
        _c2h_snd_txbf(adapter, buf, buf_len);
        break;
    }
}
#define toMbps(bytes, secs)    (rtw_division64(bytes >> 17, secs))
void rtw_bf_update_traffic(PADAPTER adapter)
{
    struct beamforming_info    *info;
    struct sounding_info *sounding;
    struct beamformee_entry *bfee;
    struct sta_info *sta;
    u8 bfee_cnt, sounding_idx, i;
    u16 tp[MAX_BEAMFORMEE_ENTRY_NUM] = {0};
    u8 tx_rate[MAX_BEAMFORMEE_ENTRY_NUM] = {0};
    u64 tx_bytes, last_bytes;
    u32 time, last_timestamp;
    u8 set_timer = _FALSE;
    info = GET_BEAMFORM_INFO(adapter);
    sounding = &info->sounding_info;
    /* Check any bfee exist? */
    bfee_cnt = info->beamformee_su_cnt + info->beamformee_mu_cnt;
    if (bfee_cnt == 0)
        return;
    for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
        bfee = &info->bfee_entry[i];
        if (_FALSE == bfee->used)
            continue;
        sta = rtw_get_stainfo(&adapter->stapriv, bfee->mac_addr);
        if (!sta) {
            RTW_ERR("%s: Cann't find sta_info for " MAC_FMT "!\n", __FUNCTION__, MAC_ARG(bfee->mac_addr));
            continue;
        }
        last_timestamp = bfee->tx_timestamp;
        last_bytes = bfee->tx_bytes;
        bfee->tx_timestamp = rtw_get_current_time();
        bfee->tx_bytes = sta->sta_stats.tx_bytes;
        if (last_timestamp) {
            if (bfee->tx_bytes >= last_bytes)
                tx_bytes = bfee->tx_bytes - last_bytes;
            else
                tx_bytes = bfee->tx_bytes + (~last_bytes);
            time = rtw_get_time_interval_ms(last_timestamp, bfee->tx_timestamp);
            time = (time > 1000) ? time/1000 : 1;
            tp[i] = toMbps(tx_bytes, time);
            tx_rate[i] = rtw_get_current_tx_rate(adapter, bfee->mac_id);
            RTW_INFO("%s: BFee idx(%d), MadId(%d), TxTP=%lld bytes (%d Mbps), txrate=%d\n",
                 __FUNCTION__, i, bfee->mac_id, tx_bytes, tp[i], tx_rate[i]);
        }
    }
    sounding_idx = phydm_get_beamforming_sounding_info(GET_PDM_ODM(adapter), tp, MAX_BEAMFORMEE_ENTRY_NUM, tx_rate);
    for (i = 0; i < MAX_BEAMFORMEE_ENTRY_NUM; i++) {
        bfee = &info->bfee_entry[i];
        if (_FALSE == bfee->used) {
            if (sounding_idx & BIT(i))
                RTW_WARN("%s: bfee(%d) not in used but need sounding?!\n", __FUNCTION__, i);
            continue;
        }
        if (sounding_idx & BIT(i)) {
            if (_FALSE == bfee->bApplySounding) {
                bfee->bApplySounding = _TRUE;
                bfee->SoundCnt = 0;
                set_timer = _TRUE;
            }
        } else {
            if (_TRUE == bfee->bApplySounding) {
                bfee->bApplySounding = _FALSE;
                bfee->bDeleteSounding = _TRUE;
                bfee->SoundCnt = 0;
                set_timer = _TRUE;
            }
        }
    }
    if (_TRUE == set_timer) {
        if (SOUNDING_STATE_NONE == info->sounding_info.state) {
            info->sounding_info.state = SOUNDING_STATE_INIT;
            _set_timer(&info->sounding_timer, 0);
        }
    }
}
#else /* !RTW_BEAMFORMING_VERSION_2 */
#if (BEAMFORMING_SUPPORT == 0) /*for diver defined beamforming*/
struct beamforming_entry    *beamforming_get_entry_by_addr(struct mlme_priv *pmlmepriv, u8 *ra, u8 *idx)
{
    u8    i = 0;
    struct beamforming_info    *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
    for (i = 0; i < BEAMFORMING_ENTRY_NUM; i++) {
        if (pBeamInfo->beamforming_entry[i].bUsed &&
            (_rtw_memcmp(ra, pBeamInfo->beamforming_entry[i].mac_addr, ETH_ALEN))) {
            *idx = i;
            return &(pBeamInfo->beamforming_entry[i]);
        }
    }
    return NULL;
}
BEAMFORMING_CAP beamforming_get_entry_beam_cap_by_mac_id(PVOID pmlmepriv , u8 mac_id)
{
    u8    i = 0;
    struct beamforming_info    *pBeamInfo = GET_BEAMFORM_INFO((struct mlme_priv *)pmlmepriv);
    BEAMFORMING_CAP        BeamformEntryCap = BEAMFORMING_CAP_NONE;
    for (i = 0; i < BEAMFORMING_ENTRY_NUM; i++) {
        if (pBeamInfo->beamforming_entry[i].bUsed &&
            (mac_id == pBeamInfo->beamforming_entry[i].mac_id)) {
            BeamformEntryCap =  pBeamInfo->beamforming_entry[i].beamforming_entry_cap;
            i = BEAMFORMING_ENTRY_NUM;
        }
    }
    return BeamformEntryCap;
}
struct beamforming_entry    *beamforming_get_free_entry(struct mlme_priv *pmlmepriv, u8 *idx)
{
    u8    i = 0;
    struct beamforming_info    *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
    for (i = 0; i < BEAMFORMING_ENTRY_NUM; i++) {
        if (pBeamInfo->beamforming_entry[i].bUsed == _FALSE) {
            *idx = i;
            return &(pBeamInfo->beamforming_entry[i]);
        }
    }
    return NULL;
}
struct beamforming_entry    *beamforming_add_entry(PADAPTER adapter, u8 *ra, u16 aid,
    u16 mac_id, CHANNEL_WIDTH bw, BEAMFORMING_CAP beamfrom_cap, u8 *idx)
{
    struct mlme_priv            *pmlmepriv = &(adapter->mlmepriv);
    struct beamforming_entry    *pEntry = beamforming_get_free_entry(pmlmepriv, idx);
    if (pEntry != NULL) {
        pEntry->bUsed = _TRUE;
        pEntry->aid = aid;
        pEntry->mac_id = mac_id;
        pEntry->sound_bw = bw;
        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
            u16    BSSID = ((*(adapter_mac_addr(adapter) + 5) & 0xf0) >> 4) ^
                (*(adapter_mac_addr(adapter) + 5) & 0xf); /* BSSID[44:47] xor BSSID[40:43] */
            pEntry->p_aid = (aid + BSSID * 32) & 0x1ff;        /* (dec(A) + dec(B)*32) mod 512 */
            pEntry->g_id = 63;
        } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
            pEntry->p_aid = 0;
            pEntry->g_id = 63;
        } else {
            pEntry->p_aid =  ra[5];                        /* BSSID[39:47] */
            pEntry->p_aid = (pEntry->p_aid << 1) | (ra[4] >> 7);
            pEntry->g_id = 0;
        }
        _rtw_memcpy(pEntry->mac_addr, ra, ETH_ALEN);
        pEntry->bSound = _FALSE;
        /* 3 TODO SW/FW sound period */
        pEntry->sound_period = 200;
        pEntry->beamforming_entry_cap = beamfrom_cap;
        pEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
        pEntry->PreLogSeq = 0;    /*Modified by Jeffery @2015-04-13*/
        pEntry->LogSeq = 0;        /*Modified by Jeffery @2014-10-29*/
        pEntry->LogRetryCnt = 0;    /*Modified by Jeffery @2014-10-29*/
        pEntry->LogSuccess = 0;    /*LogSuccess is NOT needed to be accumulated, so  LogSuccessCnt->LogSuccess, 2015-04-13, Jeffery*/
        pEntry->ClockResetTimes = 0;    /*Modified by Jeffery @2015-04-13*/
        pEntry->LogStatusFailCnt = 0;
        return pEntry;
    } else
        return NULL;
}
BOOLEAN    beamforming_remove_entry(struct mlme_priv *pmlmepriv, u8 *ra, u8 *idx)
{
    struct beamforming_entry    *pEntry = beamforming_get_entry_by_addr(pmlmepriv, ra, idx);
    if (pEntry != NULL) {
        pEntry->bUsed = _FALSE;
        pEntry->beamforming_entry_cap = BEAMFORMING_CAP_NONE;
        pEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
        return _TRUE;
    } else
        return _FALSE;
}
/* Used for BeamformingStart_V1 */
void    beamforming_dym_ndpa_rate(PADAPTER adapter)
{
    u16    NDPARate = MGN_6M;
    PHAL_DATA_TYPE    pHalData = GET_HAL_DATA(adapter);
    if (pHalData->min_undecorated_pwdb_for_dm > 30) /* link RSSI > 30% */
        NDPARate = MGN_24M;
    else
        NDPARate = MGN_6M;
    /* BW = CHANNEL_WIDTH_20; */
    NDPARate = NDPARate << 8;
    rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_RATE, (u8 *)&NDPARate);
}
void beamforming_dym_period(PADAPTER Adapter)
{
    u8    Idx;
    BOOLEAN    bChangePeriod = _FALSE;
    u16    SoundPeriod_SW, SoundPeriod_FW;
    PHAL_DATA_TYPE    pHalData = GET_HAL_DATA(Adapter);
    struct dvobj_priv    *pdvobjpriv = adapter_to_dvobj(Adapter);
    struct beamforming_entry    *pBeamformEntry;
    struct beamforming_info    *pBeamInfo = GET_BEAMFORM_INFO((&Adapter->mlmepriv));
    struct sounding_info        *pSoundInfo = &(pBeamInfo->sounding_info);
    /* 3 TODO  per-client throughput caculation. */
    if (pdvobjpriv->traffic_stat.cur_tx_tp + pdvobjpriv->traffic_stat.cur_rx_tp > 2) {
        SoundPeriod_SW = 32 * 20;
        SoundPeriod_FW = 2;
    } else {
        SoundPeriod_SW = 32 * 2000;
        SoundPeriod_FW = 200;
    }
    for (Idx = 0; Idx < BEAMFORMING_ENTRY_NUM; Idx++) {
        pBeamformEntry = pBeamInfo->beamforming_entry + Idx;
        if (pBeamformEntry->bDefaultCSI) {
            SoundPeriod_SW = 32 * 2000;
            SoundPeriod_FW = 200;
        }
        if (pBeamformEntry->beamforming_entry_cap & (BEAMFORMER_CAP_HT_EXPLICIT | BEAMFORMER_CAP_VHT_SU)) {
            if (pSoundInfo->sound_mode == SOUNDING_FW_VHT_TIMER || pSoundInfo->sound_mode == SOUNDING_FW_HT_TIMER) {
                if (pBeamformEntry->sound_period != SoundPeriod_FW) {
                    pBeamformEntry->sound_period = SoundPeriod_FW;
                    bChangePeriod = _TRUE;    /* Only FW sounding need to send H2C packet to change sound period. */
                }
            } else if (pBeamformEntry->sound_period != SoundPeriod_SW)
                pBeamformEntry->sound_period = SoundPeriod_SW;
        }
    }
    if (bChangePeriod)
        rtw_hal_set_hwreg(Adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&Idx);
}
BOOLEAN    issue_ht_sw_ndpa_packet(PADAPTER Adapter, u8 *ra, CHANNEL_WIDTH bw, u8 qidx)
{
    struct xmit_frame        *pmgntframe;
    struct pkt_attrib        *pattrib;
    struct rtw_ieee80211_hdr    *pwlanhdr;
    struct xmit_priv        *pxmitpriv = &(Adapter->xmitpriv);
    struct mlme_ext_priv    *pmlmeext = &Adapter->mlmeextpriv;
    struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
    u8    ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};
    u8    *pframe;
    u16    *fctrl;
    u16    duration = 0;
    u8    aSifsTime = 0;
    u8    NDPTxRate = 0;
    RTW_INFO("%s: issue_ht_sw_ndpa_packet!\n", __func__);
    NDPTxRate = MGN_MCS8;
    RTW_INFO("%s: NDPTxRate =%d\n", __func__, NDPTxRate);
    pmgntframe = alloc_mgtxmitframe(pxmitpriv);
    if (pmgntframe == NULL)
        return _FALSE;
    /*update attribute*/
    pattrib = &pmgntframe->attrib;
    update_mgntframe_attrib(Adapter, pattrib);
    pattrib->qsel = QSLT_MGNT;
    pattrib->rate = NDPTxRate;
    pattrib->bwmode = bw;
    pattrib->order = 1;
    pattrib->subtype = WIFI_ACTION_NOACK;
    _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
    pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
    pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
    fctrl = &pwlanhdr->frame_ctl;
    *(fctrl) = 0;
    set_order_bit(pframe);
    set_frame_sub_type(pframe, WIFI_ACTION_NOACK);
    _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
    _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(Adapter), ETH_ALEN);
    _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
    if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
        aSifsTime = 10;
    else
        aSifsTime = 16;
    duration = 2 * aSifsTime + 40;
    if (bw == CHANNEL_WIDTH_40)
        duration += 87;
    else
        duration += 180;
    set_duration(pframe, duration);
    /*HT control field*/
    SET_HT_CTRL_CSI_STEERING(pframe + 24, 3);
    SET_HT_CTRL_NDP_ANNOUNCEMENT(pframe + 24, 1);
    _rtw_memcpy(pframe + 28, ActionHdr, 4);
    pattrib->pktlen = 32;
    pattrib->last_txcmdsz = pattrib->pktlen;
    dump_mgntframe(Adapter, pmgntframe);
    return _TRUE;
}
BOOLEAN    issue_ht_ndpa_packet(PADAPTER Adapter, u8 *ra, CHANNEL_WIDTH bw, u8 qidx)
{
    struct xmit_frame        *pmgntframe;
    struct pkt_attrib        *pattrib;
    struct rtw_ieee80211_hdr    *pwlanhdr;
    struct xmit_priv        *pxmitpriv = &(Adapter->xmitpriv);
    struct mlme_ext_priv    *pmlmeext = &Adapter->mlmeextpriv;
    struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
    u8    ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};
    u8    *pframe;
    u16    *fctrl;
    u16    duration = 0;
    u8    aSifsTime = 0;
    pmgntframe = alloc_mgtxmitframe(pxmitpriv);
    if (pmgntframe == NULL)
        return _FALSE;
    /*update attribute*/
    pattrib = &pmgntframe->attrib;
    update_mgntframe_attrib(Adapter, pattrib);
    if (qidx == BCN_QUEUE_INX)
        pattrib->qsel = QSLT_BEACON;
    pattrib->rate = MGN_MCS8;
    pattrib->bwmode = bw;
    pattrib->order = 1;
    pattrib->subtype = WIFI_ACTION_NOACK;
    _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
    pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
    pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
    fctrl = &pwlanhdr->frame_ctl;
    *(fctrl) = 0;
    set_order_bit(pframe);
    set_frame_sub_type(pframe, WIFI_ACTION_NOACK);
    _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
    _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(Adapter), ETH_ALEN);
    _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
    if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
        aSifsTime = 10;
    else
        aSifsTime = 16;
    duration = 2 * aSifsTime + 40;
    if (bw == CHANNEL_WIDTH_40)
        duration += 87;
    else
        duration += 180;
    set_duration(pframe, duration);
    /* HT control field */
    SET_HT_CTRL_CSI_STEERING(pframe + 24, 3);
    SET_HT_CTRL_NDP_ANNOUNCEMENT(pframe + 24, 1);
    _rtw_memcpy(pframe + 28, ActionHdr, 4);
    pattrib->pktlen = 32;
    pattrib->last_txcmdsz = pattrib->pktlen;
    dump_mgntframe(Adapter, pmgntframe);
    return _TRUE;
}
BOOLEAN    beamforming_send_ht_ndpa_packet(PADAPTER Adapter, u8 *ra, CHANNEL_WIDTH bw, u8 qidx)
{
    return issue_ht_ndpa_packet(Adapter, ra, bw, qidx);
}
BOOLEAN    issue_vht_sw_ndpa_packet(PADAPTER Adapter, u8 *ra, u16 aid, CHANNEL_WIDTH bw, u8 qidx)
{
    struct xmit_frame        *pmgntframe;
    struct pkt_attrib        *pattrib;
    struct rtw_ieee80211_hdr    *pwlanhdr;
    struct xmit_priv        *pxmitpriv = &(Adapter->xmitpriv);
    struct mlme_ext_priv    *pmlmeext = &Adapter->mlmeextpriv;
    struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
    struct mlme_priv        *pmlmepriv = &(Adapter->mlmepriv);
    struct beamforming_info    *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
    struct rtw_ndpa_sta_info    sta_info;
    u8         NDPTxRate = 0;
    u8    *pframe;
    u16    *fctrl;
    u16    duration = 0;
    u8    sequence = 0, aSifsTime = 0;
    RTW_INFO("%s: issue_vht_sw_ndpa_packet!\n", __func__);
    NDPTxRate = MGN_VHT2SS_MCS0;
    RTW_INFO("%s: NDPTxRate =%d\n", __func__, NDPTxRate);
    pmgntframe = alloc_mgtxmitframe(pxmitpriv);
    if (pmgntframe == NULL) {
        RTW_INFO("%s, alloc mgnt frame fail\n", __func__);
        return _FALSE;
    }
    /*update attribute*/
    pattrib = &pmgntframe->attrib;
    update_mgntframe_attrib(Adapter, pattrib);
    pattrib->qsel = QSLT_MGNT;
    pattrib->rate = NDPTxRate;
    pattrib->bwmode = bw;
    pattrib->subtype = WIFI_NDPA;
    _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
    pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
    pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
    fctrl = &pwlanhdr->frame_ctl;
    *(fctrl) = 0;
    set_frame_sub_type(pframe, WIFI_NDPA);
    _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
    _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(Adapter), ETH_ALEN);
    if (is_supported_5g(pmlmeext->cur_wireless_mode) || is_supported_ht(pmlmeext->cur_wireless_mode))
        aSifsTime = 16;
    else
        aSifsTime = 10;
    duration = 2 * aSifsTime + 44;
    if (bw == CHANNEL_WIDTH_80)
        duration += 40;
    else if (bw == CHANNEL_WIDTH_40)
        duration += 87;
    else
        duration += 180;
    set_duration(pframe, duration);
    sequence = pBeamInfo->sounding_sequence << 2;
    if (pBeamInfo->sounding_sequence >= 0x3f)
        pBeamInfo->sounding_sequence = 0;
    else
        pBeamInfo->sounding_sequence++;
    _rtw_memcpy(pframe + 16, &sequence, 1);
    if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
        aid = 0;
    sta_info.aid = aid;
    sta_info.feedback_type = 0;
    sta_info.nc_index = 0;
    _rtw_memcpy(pframe + 17, (u8 *)&sta_info, 2);
    pattrib->pktlen = 19;
    pattrib->last_txcmdsz = pattrib->pktlen;
    dump_mgntframe(Adapter, pmgntframe);
    return _TRUE;
}
BOOLEAN    issue_vht_ndpa_packet(PADAPTER Adapter, u8 *ra, u16 aid, CHANNEL_WIDTH bw, u8 qidx)
{
    struct xmit_frame        *pmgntframe;
    struct pkt_attrib        *pattrib;
    struct rtw_ieee80211_hdr    *pwlanhdr;
    struct xmit_priv        *pxmitpriv = &(Adapter->xmitpriv);
    struct mlme_ext_priv    *pmlmeext = &Adapter->mlmeextpriv;
    struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
    struct mlme_priv        *pmlmepriv = &(Adapter->mlmepriv);
    struct beamforming_info    *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
    struct rtw_ndpa_sta_info    sta_info;
    u8    *pframe;
    u16    *fctrl;
    u16    duration = 0;
    u8    sequence = 0, aSifsTime = 0;
    pmgntframe = alloc_mgtxmitframe(pxmitpriv);
    if (pmgntframe == NULL)
        return _FALSE;
    /*update attribute*/
    pattrib = &pmgntframe->attrib;
    update_mgntframe_attrib(Adapter, pattrib);
    if (qidx == BCN_QUEUE_INX)
        pattrib->qsel = QSLT_BEACON;
    pattrib->rate = MGN_VHT2SS_MCS0;
    pattrib->bwmode = bw;
    pattrib->subtype = WIFI_NDPA;
    _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
    pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
    pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
    fctrl = &pwlanhdr->frame_ctl;
    *(fctrl) = 0;
    set_frame_sub_type(pframe, WIFI_NDPA);
    _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
    _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(Adapter), ETH_ALEN);
    if (is_supported_5g(pmlmeext->cur_wireless_mode) || is_supported_ht(pmlmeext->cur_wireless_mode))
        aSifsTime = 16;
    else
        aSifsTime = 10;
    duration = 2 * aSifsTime + 44;
    if (bw == CHANNEL_WIDTH_80)
        duration += 40;
    else if (bw == CHANNEL_WIDTH_40)
        duration += 87;
    else
        duration += 180;
    set_duration(pframe, duration);
    sequence = pBeamInfo->sounding_sequence << 2;
    if (pBeamInfo->sounding_sequence >= 0x3f)
        pBeamInfo->sounding_sequence = 0;
    else
        pBeamInfo->sounding_sequence++;
    _rtw_memcpy(pframe + 16, &sequence, 1);
    if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
        aid = 0;
    sta_info.aid = aid;
    sta_info.feedback_type = 0;
    sta_info.nc_index = 0;
    _rtw_memcpy(pframe + 17, (u8 *)&sta_info, 2);
    pattrib->pktlen = 19;
    pattrib->last_txcmdsz = pattrib->pktlen;
    dump_mgntframe(Adapter, pmgntframe);
    return _TRUE;
}
BOOLEAN    beamforming_send_vht_ndpa_packet(PADAPTER Adapter, u8 *ra, u16 aid, CHANNEL_WIDTH bw, u8 qidx)
{
    return issue_vht_ndpa_packet(Adapter, ra, aid, bw, qidx);
}
BOOLEAN    beamfomring_bSounding(struct beamforming_info *pBeamInfo)
{
    BOOLEAN        bSounding = _FALSE;
    if ((beamforming_get_beamform_cap(pBeamInfo) & BEAMFORMER_CAP) == 0)
        bSounding = _FALSE;
    else
        bSounding = _TRUE;
    return bSounding;
}
u8    beamforming_sounding_idx(struct beamforming_info *pBeamInfo)
{
    u8    idx = 0;
    u8    i;
    for (i = 0; i < BEAMFORMING_ENTRY_NUM; i++) {
        if (pBeamInfo->beamforming_entry[i].bUsed &&
            (_FALSE == pBeamInfo->beamforming_entry[i].bSound)) {
            idx = i;
            break;
        }
    }
    return idx;
}
SOUNDING_MODE    beamforming_sounding_mode(struct beamforming_info *pBeamInfo, u8 idx)
{
    struct beamforming_entry    BeamEntry = pBeamInfo->beamforming_entry[idx];
    SOUNDING_MODE    mode;
    if (BeamEntry.beamforming_entry_cap & BEAMFORMER_CAP_VHT_SU)
        mode = SOUNDING_FW_VHT_TIMER;
    else if (BeamEntry.beamforming_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT)
        mode = SOUNDING_FW_HT_TIMER;
    else
        mode = SOUNDING_STOP_All_TIMER;
    return mode;
}
u16    beamforming_sounding_time(struct beamforming_info *pBeamInfo, SOUNDING_MODE mode, u8 idx)
{
    u16                        sounding_time = 0xffff;
    struct beamforming_entry    BeamEntry = pBeamInfo->beamforming_entry[idx];
    sounding_time = BeamEntry.sound_period;
    return sounding_time;
}
CHANNEL_WIDTH    beamforming_sounding_bw(struct beamforming_info *pBeamInfo, SOUNDING_MODE mode, u8 idx)
{
    CHANNEL_WIDTH                sounding_bw = CHANNEL_WIDTH_20;
    struct beamforming_entry        BeamEntry = pBeamInfo->beamforming_entry[idx];
    sounding_bw = BeamEntry.sound_bw;
    return sounding_bw;
}
BOOLEAN    beamforming_select_beam_entry(struct beamforming_info *pBeamInfo)
{
    struct sounding_info        *pSoundInfo = &(pBeamInfo->sounding_info);
    pSoundInfo->sound_idx = beamforming_sounding_idx(pBeamInfo);
    if (pSoundInfo->sound_idx < BEAMFORMING_ENTRY_NUM)
        pSoundInfo->sound_mode = beamforming_sounding_mode(pBeamInfo, pSoundInfo->sound_idx);
    else
        pSoundInfo->sound_mode = SOUNDING_STOP_All_TIMER;
    if (SOUNDING_STOP_All_TIMER == pSoundInfo->sound_mode)
        return _FALSE;
    else {
        pSoundInfo->sound_bw = beamforming_sounding_bw(pBeamInfo, pSoundInfo->sound_mode, pSoundInfo->sound_idx);
        pSoundInfo->sound_period = beamforming_sounding_time(pBeamInfo, pSoundInfo->sound_mode, pSoundInfo->sound_idx);
        return _TRUE;
    }
}
BOOLEAN    beamforming_start_fw(PADAPTER adapter, u8 idx)
{
    u8                        *RA = NULL;
    struct beamforming_entry    *pEntry;
    BOOLEAN                    ret = _TRUE;
    struct mlme_priv            *pmlmepriv = &(adapter->mlmepriv);
    struct beamforming_info    *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
    pEntry = &(pBeamInfo->beamforming_entry[idx]);
    if (pEntry->bUsed == _FALSE) {
        RTW_INFO("Skip Beamforming, no entry for Idx =%d\n", idx);
        return _FALSE;
    }
    pEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_PROGRESSING;
    pEntry->bSound = _TRUE;
    rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&idx);
    return _TRUE;
}
void    beamforming_end_fw(PADAPTER adapter)
{
    u8    idx = 0;
    rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&idx);
    RTW_INFO("%s\n", __FUNCTION__);
}
BOOLEAN    beamforming_start_period(PADAPTER adapter)
{
    BOOLEAN    ret = _TRUE;
    struct mlme_priv            *pmlmepriv = &(adapter->mlmepriv);
    struct beamforming_info    *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
    struct sounding_info        *pSoundInfo = &(pBeamInfo->sounding_info);
    beamforming_dym_ndpa_rate(adapter);
    beamforming_select_beam_entry(pBeamInfo);
    if (pSoundInfo->sound_mode == SOUNDING_FW_VHT_TIMER || pSoundInfo->sound_mode == SOUNDING_FW_HT_TIMER)
        ret = beamforming_start_fw(adapter, pSoundInfo->sound_idx);
    else
        ret = _FALSE;
    RTW_INFO("%s Idx %d Mode %d BW %d Period %d\n", __FUNCTION__,
        pSoundInfo->sound_idx, pSoundInfo->sound_mode, pSoundInfo->sound_bw, pSoundInfo->sound_period);
    return ret;
}
void    beamforming_end_period(PADAPTER adapter)
{
    u8                        idx = 0;
    struct beamforming_entry    *pBeamformEntry;
    struct mlme_priv            *pmlmepriv = &(adapter->mlmepriv);
    struct beamforming_info    *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
    struct sounding_info        *pSoundInfo = &(pBeamInfo->sounding_info);
    if (pSoundInfo->sound_mode == SOUNDING_FW_VHT_TIMER || pSoundInfo->sound_mode == SOUNDING_FW_HT_TIMER)
        beamforming_end_fw(adapter);
}
void    beamforming_notify(PADAPTER adapter)
{
    BOOLEAN        bSounding = _FALSE;
    struct beamforming_info    *pBeamInfo = GET_BEAMFORM_INFO(&(adapter->mlmepriv));
    bSounding = beamfomring_bSounding(pBeamInfo);
    if (pBeamInfo->beamforming_state == BEAMFORMING_STATE_IDLE) {
        if (bSounding) {
            if (beamforming_start_period(adapter) == _TRUE)
                pBeamInfo->beamforming_state = BEAMFORMING_STATE_START;
        }
    } else if (pBeamInfo->beamforming_state == BEAMFORMING_STATE_START) {
        if (bSounding) {
            if (beamforming_start_period(adapter) == _FALSE)
                pBeamInfo->beamforming_state = BEAMFORMING_STATE_END;
        } else {
            beamforming_end_period(adapter);
            pBeamInfo->beamforming_state = BEAMFORMING_STATE_END;
        }
    } else if (pBeamInfo->beamforming_state == BEAMFORMING_STATE_END) {
        if (bSounding) {
            if (beamforming_start_period(adapter) == _TRUE)
                pBeamInfo->beamforming_state = BEAMFORMING_STATE_START;
        }
    } else
        RTW_INFO("%s BeamformState %d\n", __FUNCTION__, pBeamInfo->beamforming_state);
    RTW_INFO("%s BeamformState %d bSounding %d\n", __FUNCTION__, pBeamInfo->beamforming_state, bSounding);
}
BOOLEAN    beamforming_init_entry(PADAPTER    adapter, struct sta_info *psta, u8 *idx)
{
    struct mlme_priv    *pmlmepriv = &(adapter->mlmepriv);
    struct ht_priv        *phtpriv = &(pmlmepriv->htpriv);
#ifdef CONFIG_80211AC_VHT
    struct vht_priv        *pvhtpriv = &(pmlmepriv->vhtpriv);
#endif
    struct mlme_ext_priv    *pmlmeext = &(adapter->mlmeextpriv);
    struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
    struct beamforming_entry    *pBeamformEntry = NULL;
    u8    *ra;
    u16    aid, mac_id;
    u8    wireless_mode;
    CHANNEL_WIDTH    bw = CHANNEL_WIDTH_20;
    BEAMFORMING_CAP    beamform_cap = BEAMFORMING_CAP_NONE;
    /* The current setting does not support Beaforming */
    if (0 == phtpriv->beamform_cap
#ifdef CONFIG_80211AC_VHT
        && 0 == pvhtpriv->beamform_cap
#endif
       ) {
        RTW_INFO("The configuration disabled Beamforming! Skip...\n");
        return _FALSE;
    }
    aid = psta->aid;
    ra = psta->hwaddr;
    mac_id = psta->mac_id;
    wireless_mode = psta->wireless_mode;
    bw = psta->bw_mode;
    if (is_supported_ht(wireless_mode) || is_supported_vht(wireless_mode)) {
        /* 3 */ /* HT */
        u8    cur_beamform;
        cur_beamform = psta->htpriv.beamform_cap;
        /* We are Beamformee because the STA is Beamformer */
        if (TEST_FLAG(cur_beamform, BEAMFORMING_HT_BEAMFORMER_ENABLE))
            beamform_cap = (BEAMFORMING_CAP)(beamform_cap | BEAMFORMEE_CAP_HT_EXPLICIT);
        /* We are Beamformer because the STA is Beamformee */
        if (TEST_FLAG(cur_beamform, BEAMFORMING_HT_BEAMFORMEE_ENABLE))
            beamform_cap = (BEAMFORMING_CAP)(beamform_cap | BEAMFORMER_CAP_HT_EXPLICIT);
#ifdef CONFIG_80211AC_VHT
        if (is_supported_vht(wireless_mode)) {
            /* 3 */ /* VHT */
            cur_beamform = psta->vhtpriv.beamform_cap;
            /* We are Beamformee because the STA is Beamformer */
            if (TEST_FLAG(cur_beamform, BEAMFORMING_VHT_BEAMFORMER_ENABLE))
                beamform_cap = (BEAMFORMING_CAP)(beamform_cap | BEAMFORMEE_CAP_VHT_SU);
            /* We are Beamformer because the STA is Beamformee */
            if (TEST_FLAG(cur_beamform, BEAMFORMING_VHT_BEAMFORMEE_ENABLE))
                beamform_cap = (BEAMFORMING_CAP)(beamform_cap | BEAMFORMER_CAP_VHT_SU);
        }
#endif /* CONFIG_80211AC_VHT */
        if (beamform_cap == BEAMFORMING_CAP_NONE)
            return _FALSE;
        RTW_INFO("Beamforming Config Capability = 0x%02X\n", beamform_cap);
        pBeamformEntry = beamforming_get_entry_by_addr(pmlmepriv, ra, idx);
        if (pBeamformEntry == NULL) {
            pBeamformEntry = beamforming_add_entry(adapter, ra, aid, mac_id, bw, beamform_cap, idx);
            if (pBeamformEntry == NULL)
                return _FALSE;
            else
                pBeamformEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZEING;
        } else {
            /* Entry has been created. If entry is initialing or progressing then errors occur. */
            if (pBeamformEntry->beamforming_entry_state != BEAMFORMING_ENTRY_STATE_INITIALIZED &&
                pBeamformEntry->beamforming_entry_state != BEAMFORMING_ENTRY_STATE_PROGRESSED) {
                RTW_INFO("Error State of Beamforming");
                return _FALSE;
            } else
                pBeamformEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZEING;
        }
        pBeamformEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZED;
        psta->txbf_paid = pBeamformEntry->p_aid;
        psta->txbf_gid = pBeamformEntry->g_id;
        RTW_INFO("%s Idx %d\n", __FUNCTION__, *idx);
    } else
        return _FALSE;
    return _SUCCESS;
}
void    beamforming_deinit_entry(PADAPTER adapter, u8 *ra)
{
    u8    idx = 0;
    struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
    if (beamforming_remove_entry(pmlmepriv, ra, &idx) == _TRUE)
        rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_LEAVE, (u8 *)&idx);
    RTW_INFO("%s Idx %d\n", __FUNCTION__, idx);
}
void    beamforming_reset(PADAPTER adapter)
{
    u8    idx = 0;
    struct mlme_priv            *pmlmepriv = &(adapter->mlmepriv);
    struct beamforming_info    *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
    for (idx = 0; idx < BEAMFORMING_ENTRY_NUM; idx++) {
        if (pBeamInfo->beamforming_entry[idx].bUsed == _TRUE) {
            pBeamInfo->beamforming_entry[idx].bUsed = _FALSE;
            pBeamInfo->beamforming_entry[idx].beamforming_entry_cap = BEAMFORMING_CAP_NONE;
            pBeamInfo->beamforming_entry[idx].beamforming_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
            rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_LEAVE, (u8 *)&idx);
        }
    }
    RTW_INFO("%s\n", __FUNCTION__);
}
void beamforming_sounding_fail(PADAPTER Adapter)
{
    struct mlme_priv            *pmlmepriv = &(Adapter->mlmepriv);
    struct beamforming_info    *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
    struct beamforming_entry    *pEntry = &(pBeamInfo->beamforming_entry[pBeamInfo->beamforming_cur_idx]);
    pEntry->bSound = _FALSE;
    rtw_hal_set_hwreg(Adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&pBeamInfo->beamforming_cur_idx);
    beamforming_deinit_entry(Adapter, pEntry->mac_addr);
}
void    beamforming_check_sounding_success(PADAPTER Adapter, BOOLEAN status)
{
    struct mlme_priv            *pmlmepriv = &(Adapter->mlmepriv);
    struct beamforming_info    *pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
    struct beamforming_entry    *pEntry = &(pBeamInfo->beamforming_entry[pBeamInfo->beamforming_cur_idx]);
    if (status == 1)
        pEntry->LogStatusFailCnt = 0;
    else {
        pEntry->LogStatusFailCnt++;
        RTW_INFO("%s LogStatusFailCnt %d\n", __FUNCTION__, pEntry->LogStatusFailCnt);
    }
    if (pEntry->LogStatusFailCnt > 20) {
        RTW_INFO("%s LogStatusFailCnt > 20, Stop SOUNDING\n", __FUNCTION__);
        /* pEntry->bSound = _FALSE; */
        /* rtw_hal_set_hwreg(Adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&pBeamInfo->beamforming_cur_idx); */
        /* beamforming_deinit_entry(Adapter, pEntry->mac_addr); */
        beamforming_wk_cmd(Adapter, BEAMFORMING_CTRL_SOUNDING_FAIL, NULL, 0, 1);
    }
}
void    beamforming_enter(PADAPTER adapter, PVOID psta)
{
    u8    idx = 0xff;
    if (beamforming_init_entry(adapter, (struct sta_info *)psta, &idx))
        rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_ENTER, (u8 *)&idx);
    /* RTW_INFO("%s Idx %d\n", __FUNCTION__, idx); */
}
void    beamforming_leave(PADAPTER adapter, u8 *ra)
{
    if (ra == NULL)
        beamforming_reset(adapter);
    else
        beamforming_deinit_entry(adapter, ra);
    beamforming_notify(adapter);
}
BEAMFORMING_CAP beamforming_get_beamform_cap(struct beamforming_info    *pBeamInfo)
{
    u8    i;
    BOOLEAN                bSelfBeamformer = _FALSE;
    BOOLEAN                bSelfBeamformee = _FALSE;
    struct beamforming_entry    beamforming_entry;
    BEAMFORMING_CAP        beamform_cap = BEAMFORMING_CAP_NONE;
    for (i = 0; i < BEAMFORMING_ENTRY_NUM; i++) {
        beamforming_entry = pBeamInfo->beamforming_entry[i];
        if (beamforming_entry.bUsed) {
            if ((beamforming_entry.beamforming_entry_cap & BEAMFORMEE_CAP_VHT_SU) ||
                (beamforming_entry.beamforming_entry_cap & BEAMFORMEE_CAP_HT_EXPLICIT))
                bSelfBeamformee = _TRUE;
            if ((beamforming_entry.beamforming_entry_cap & BEAMFORMER_CAP_VHT_SU) ||
                (beamforming_entry.beamforming_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT))
                bSelfBeamformer = _TRUE;
        }
        if (bSelfBeamformer && bSelfBeamformee)
            i = BEAMFORMING_ENTRY_NUM;
    }
    if (bSelfBeamformer)
        beamform_cap |= BEAMFORMER_CAP;
    if (bSelfBeamformee)
        beamform_cap |= BEAMFORMEE_CAP;
    return beamform_cap;
}
void    beamforming_watchdog(PADAPTER Adapter)
{
    struct beamforming_info    *pBeamInfo = GET_BEAMFORM_INFO((&(Adapter->mlmepriv)));
    if (pBeamInfo->beamforming_state != BEAMFORMING_STATE_START)
        return;
    beamforming_dym_period(Adapter);
    beamforming_dym_ndpa_rate(Adapter);
}
#endif/* #if (BEAMFORMING_SUPPORT ==0) - for diver defined beamforming*/
u32    rtw_beamforming_get_report_frame(PADAPTER     Adapter, union recv_frame *precv_frame)
{
    u32    ret = _SUCCESS;
#if (BEAMFORMING_SUPPORT == 1)
    PHAL_DATA_TYPE    pHalData = GET_HAL_DATA(Adapter);
    struct PHY_DM_STRUCT        *pDM_Odm = &(pHalData->odmpriv);
    ret = beamforming_get_report_frame(pDM_Odm, precv_frame);
#else /*(BEAMFORMING_SUPPORT == 0)- for drv beamfoming*/
    struct beamforming_entry    *pBeamformEntry = NULL;
    struct mlme_priv            *pmlmepriv = &(Adapter->mlmepriv);
    u8    *pframe = precv_frame->u.hdr.rx_data;
    u32    frame_len = precv_frame->u.hdr.len;
    u8    *ta;
    u8    idx, offset;
    /*RTW_INFO("rtw_beamforming_get_report_frame\n");*/
    /*Memory comparison to see if CSI report is the same with previous one*/
    ta = get_addr2_ptr(pframe);
    pBeamformEntry = beamforming_get_entry_by_addr(pmlmepriv, ta, &idx);
    if (pBeamformEntry->beamforming_entry_cap & BEAMFORMER_CAP_VHT_SU)
        offset = 31;    /*24+(1+1+3)+2  MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)*/
    else if (pBeamformEntry->beamforming_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT)
        offset = 34;    /*24+(1+1+6)+2  MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)*/
    else
        return ret;
    /*RTW_INFO("%s MacId %d offset=%d\n", __FUNCTION__, pBeamformEntry->mac_id, offset);*/
    if (_rtw_memcmp(pBeamformEntry->PreCsiReport + offset, pframe + offset, frame_len - offset) == _FALSE)
        pBeamformEntry->DefaultCsiCnt = 0;
    else
        pBeamformEntry->DefaultCsiCnt++;
    _rtw_memcpy(&pBeamformEntry->PreCsiReport, pframe, frame_len);
    pBeamformEntry->bDefaultCSI = _FALSE;
    if (pBeamformEntry->DefaultCsiCnt > 20)
        pBeamformEntry->bDefaultCSI = _TRUE;
    else
        pBeamformEntry->bDefaultCSI = _FALSE;
#endif
    return ret;
}
void    rtw_beamforming_get_ndpa_frame(PADAPTER     Adapter, union recv_frame *precv_frame)
{
#if (BEAMFORMING_SUPPORT == 1)
    PHAL_DATA_TYPE    pHalData = GET_HAL_DATA(Adapter);
    struct PHY_DM_STRUCT        *pDM_Odm = &(pHalData->odmpriv);
    beamforming_get_ndpa_frame(pDM_Odm, precv_frame);
#else /*(BEAMFORMING_SUPPORT == 0)- for drv beamfoming*/
    u8    *ta;
    u8    idx, Sequence;
    u8    *pframe = precv_frame->u.hdr.rx_data;
    struct mlme_priv            *pmlmepriv = &(Adapter->mlmepriv);
    struct beamforming_entry    *pBeamformEntry = NULL;
    /*RTW_INFO("rtw_beamforming_get_ndpa_frame\n");*/
    if (IS_HARDWARE_TYPE_8812(Adapter) == _FALSE)
        return;
    else if (get_frame_sub_type(pframe) != WIFI_NDPA)
        return;
    ta = get_addr2_ptr(pframe);
    /*Remove signaling TA. */
    ta[0] = ta[0] & 0xFE;
    pBeamformEntry = beamforming_get_entry_by_addr(pmlmepriv, ta, &idx);
    if (pBeamformEntry == NULL)
        return;
    else if (!(pBeamformEntry->beamforming_entry_cap & BEAMFORMEE_CAP_VHT_SU))
        return;
    /*LogSuccess: As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is NO LONGER needed !2015-04-10, Jeffery*/
    /*ClockResetTimes: While BFer entry always doesn't receive our CSI, clock will reset again and again.So ClockResetTimes is limited to 5 times.2015-04-13, Jeffery*/
    else if ((pBeamformEntry->LogSuccess == 1) || (pBeamformEntry->ClockResetTimes == 5)) {
        RTW_INFO("[%s] LogSeq=%d, PreLogSeq=%d\n", __func__, pBeamformEntry->LogSeq, pBeamformEntry->PreLogSeq);
        return;
    }
    Sequence = (pframe[16]) >> 2;
    RTW_INFO("[%s] Start, Sequence=%d, LogSeq=%d, PreLogSeq=%d, LogRetryCnt=%d, ClockResetTimes=%d, LogSuccess=%d\n",
        __func__, Sequence, pBeamformEntry->LogSeq, pBeamformEntry->PreLogSeq, pBeamformEntry->LogRetryCnt, pBeamformEntry->ClockResetTimes, pBeamformEntry->LogSuccess);
    if ((pBeamformEntry->LogSeq != 0) && (pBeamformEntry->PreLogSeq != 0)) {
        /*Success condition*/
        if ((pBeamformEntry->LogSeq != Sequence) && (pBeamformEntry->PreLogSeq != pBeamformEntry->LogSeq)) {
            /* break option for clcok reset, 2015-03-30, Jeffery */
            pBeamformEntry->LogRetryCnt = 0;
            /*As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is no longer needed.*/
            /*That is, LogSuccess is NOT needed to be reset to zero, 2015-04-13, Jeffery*/
            pBeamformEntry->LogSuccess = 1;
        } else {/*Fail condition*/
            if (pBeamformEntry->LogRetryCnt == 5) {
                pBeamformEntry->ClockResetTimes++;
                pBeamformEntry->LogRetryCnt = 0;
                RTW_INFO("[%s] Clock Reset!!! ClockResetTimes=%d\n",  __func__, pBeamformEntry->ClockResetTimes);
                beamforming_wk_cmd(Adapter, BEAMFORMING_CTRL_SOUNDING_CLK, NULL, 0, 1);
            } else
                pBeamformEntry->LogRetryCnt++;
        }
    }
    /*Update LogSeq & PreLogSeq*/
    pBeamformEntry->PreLogSeq = pBeamformEntry->LogSeq;
    pBeamformEntry->LogSeq = Sequence;
#endif
}
void    beamforming_wk_hdl(_adapter *padapter, u8 type, u8 *pbuf)
{
    PHAL_DATA_TYPE    pHalData = GET_HAL_DATA(padapter);
    struct PHY_DM_STRUCT        *pDM_Odm = &(pHalData->odmpriv);
#if (BEAMFORMING_SUPPORT == 1) /*(BEAMFORMING_SUPPORT == 1)- for PHYDM beamfoming*/
    switch (type) {
    case BEAMFORMING_CTRL_ENTER: {
        struct sta_info    *psta = (PVOID)pbuf;
        u16            staIdx = psta->mac_id;
        beamforming_enter(pDM_Odm, staIdx);
        break;
    }
    case BEAMFORMING_CTRL_LEAVE:
        beamforming_leave(pDM_Odm, pbuf);
        break;
    default:
        break;
    }
#else /*(BEAMFORMING_SUPPORT == 0)- for drv beamfoming*/
    switch (type) {
    case BEAMFORMING_CTRL_ENTER:
        beamforming_enter(padapter, (PVOID)pbuf);
        break;
    case BEAMFORMING_CTRL_LEAVE:
        beamforming_leave(padapter, pbuf);
        break;
    case BEAMFORMING_CTRL_SOUNDING_FAIL:
        beamforming_sounding_fail(padapter);
        break;
    case BEAMFORMING_CTRL_SOUNDING_CLK:
        rtw_hal_set_hwreg(padapter, HW_VAR_SOUNDING_CLK, NULL);
        break;
    default:
        break;
    }
#endif
}
u8    beamforming_wk_cmd(_adapter *padapter, s32 type, u8 *pbuf, s32 size, u8 enqueue)
{
    struct cmd_obj    *ph2c;
    struct drvextra_cmd_parm    *pdrvextra_cmd_parm;
    struct cmd_priv    *pcmdpriv = &padapter->cmdpriv;
    u8    res = _SUCCESS;
    if (enqueue) {
        u8    *wk_buf;
        ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
        if (ph2c == NULL) {
            res = _FAIL;
            goto exit;
        }
        pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
        if (pdrvextra_cmd_parm == NULL) {
            rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
            res = _FAIL;
            goto exit;
        }
        if (pbuf != NULL) {
            wk_buf = rtw_zmalloc(size);
            if (wk_buf == NULL) {
                rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
                rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
                res = _FAIL;
                goto exit;
            }
            _rtw_memcpy(wk_buf, pbuf, size);
        } else {
            wk_buf = NULL;
            size = 0;
        }
        pdrvextra_cmd_parm->ec_id = BEAMFORMING_WK_CID;
        pdrvextra_cmd_parm->type = type;
        pdrvextra_cmd_parm->size = size;
        pdrvextra_cmd_parm->pbuf = wk_buf;
        init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
        res = rtw_enqueue_cmd(pcmdpriv, ph2c);
    } else
        beamforming_wk_hdl(padapter, type, pbuf);
exit:
    return res;
}
void update_attrib_txbf_info(_adapter *padapter, struct pkt_attrib *pattrib, struct sta_info *psta)
{
    if (psta) {
        pattrib->txbf_g_id = psta->txbf_gid;
        pattrib->txbf_p_aid = psta->txbf_paid;
    }
}
#endif /* !RTW_BEAMFORMING_VERSION_2 */
#endif /* CONFIG_BEAMFORMING */
linux-bsp/drivers/rtl8188eus/core/rtw_br_ext.c
New file
@@ -0,0 +1,1585 @@
/******************************************************************************
 *
 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 *
 ******************************************************************************/
#define _RTW_BR_EXT_C_
#ifdef __KERNEL__
    #include <linux/if_arp.h>
    #include <net/ip.h>
    #include <net/ipx.h>
    #include <linux/atalk.h>
    #include <linux/udp.h>
    #include <linux/if_pppox.h>
#endif
#if 1    /* rtw_wifi_driver */
    #include <drv_types.h>
#else    /* rtw_wifi_driver */
    #include "./8192cd_cfg.h"
    #ifndef __KERNEL__
        #include "./sys-support.h"
    #endif
    #include "./8192cd.h"
    #include "./8192cd_headers.h"
    #include "./8192cd_br_ext.h"
    #include "./8192cd_debug.h"
#endif /* rtw_wifi_driver */
#ifdef CL_IPV6_PASS
    #ifdef __KERNEL__
        #include <linux/ipv6.h>
        #include <linux/icmpv6.h>
        #include <net/ndisc.h>
        #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24))
            #include <net/ip6_checksum.h>
        #else
            #include <net/checksum.h>
        #endif
    #endif
#endif
#ifdef CONFIG_BR_EXT
/* #define BR_EXT_DEBUG */
#define NAT25_IPV4        01
#define NAT25_IPV6        02
#define NAT25_IPX        03
#define NAT25_APPLE        04
#define NAT25_PPPOE        05
#define RTL_RELAY_TAG_LEN (ETH_ALEN)
#define TAG_HDR_LEN        4
#define MAGIC_CODE        0x8186
#define MAGIC_CODE_LEN    2
#define WAIT_TIME_PPPOE    5    /* waiting time for pppoe server in sec */
/*-----------------------------------------------------------------
  How database records network address:
           0    1    2    3    4    5    6    7    8    9   10
        |----|----|----|----|----|----|----|----|----|----|----|
  IPv4  |type|                             |      IP addr      |
  IPX   |type|      Net addr     |          Node addr          |
  IPX   |type|      Net addr     |Sckt addr|
  Apple |type| Network |node|
  PPPoE |type|   SID   |           AC MAC            |
-----------------------------------------------------------------*/
/* Find a tag in pppoe frame and return the pointer */
static __inline__ unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type)
{
    unsigned char *cur_ptr, *start_ptr;
    unsigned short tagLen, tagType;
    start_ptr = cur_ptr = (unsigned char *)ph->tag;
    while ((cur_ptr - start_ptr) < ntohs(ph->length)) {
        /* prevent un-alignment access */
        tagType = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]);
        tagLen  = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]);
        if (tagType == type)
            return cur_ptr;
        cur_ptr = cur_ptr + TAG_HDR_LEN + tagLen;
    }
    return 0;
}
static __inline__ int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag)
{
    struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
    int data_len;
    data_len = tag->tag_len + TAG_HDR_LEN;
    if (skb_tailroom(skb) < data_len) {
        _DEBUG_ERR("skb_tailroom() failed in add SID tag!\n");
        return -1;
    }
    skb_put(skb, data_len);
    /* have a room for new tag */
    memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length));
    ph->length = htons(ntohs(ph->length) + data_len);
    memcpy((unsigned char *)ph->tag, tag, data_len);
    return data_len;
}
static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len)
{
    int tail_len;
    unsigned long end, tail;
    if ((src + len) > skb_tail_pointer(skb) || skb->len < len)
        return -1;
    tail = (unsigned long)skb_tail_pointer(skb);
    end = (unsigned long)src + len;
    if (tail < end)
        return -1;
    tail_len = (int)(tail - end);
    if (tail_len > 0)
        memmove(src, src + len, tail_len);
    skb_trim(skb, skb->len - len);
    return 0;
}
static __inline__ unsigned long __nat25_timeout(_adapter *priv)
{
    unsigned long timeout;
    timeout = jiffies - NAT25_AGEING_TIME * HZ;
    return timeout;
}
static __inline__ int  __nat25_has_expired(_adapter *priv,
        struct nat25_network_db_entry *fdb)
{
    if (time_before_eq(fdb->ageing_timer, __nat25_timeout(priv)))
        return 1;
    return 0;
}
static __inline__ void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr,
        unsigned int *ipAddr)
{
    memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
    networkAddr[0] = NAT25_IPV4;
    memcpy(networkAddr + 7, (unsigned char *)ipAddr, 4);
}
static __inline__ void __nat25_generate_ipx_network_addr_with_node(unsigned char *networkAddr,
        unsigned int *ipxNetAddr, unsigned char *ipxNodeAddr)
{
    memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
    networkAddr[0] = NAT25_IPX;
    memcpy(networkAddr + 1, (unsigned char *)ipxNetAddr, 4);
    memcpy(networkAddr + 5, ipxNodeAddr, 6);
}
static __inline__ void __nat25_generate_ipx_network_addr_with_socket(unsigned char *networkAddr,
        unsigned int *ipxNetAddr, unsigned short *ipxSocketAddr)
{
    memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
    networkAddr[0] = NAT25_IPX;
    memcpy(networkAddr + 1, (unsigned char *)ipxNetAddr, 4);
    memcpy(networkAddr + 5, (unsigned char *)ipxSocketAddr, 2);
}
static __inline__ void __nat25_generate_apple_network_addr(unsigned char *networkAddr,
        unsigned short *network, unsigned char *node)
{
    memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
    networkAddr[0] = NAT25_APPLE;
    memcpy(networkAddr + 1, (unsigned char *)network, 2);
    networkAddr[3] = *node;
}
static __inline__ void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr,
        unsigned char *ac_mac, unsigned short *sid)
{
    memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
    networkAddr[0] = NAT25_PPPOE;
    memcpy(networkAddr + 1, (unsigned char *)sid, 2);
    memcpy(networkAddr + 3, (unsigned char *)ac_mac, 6);
}
#ifdef CL_IPV6_PASS
static  void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr,
        unsigned int *ipAddr)
{
    memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
    networkAddr[0] = NAT25_IPV6;
    memcpy(networkAddr + 1, (unsigned char *)ipAddr, 16);
}
static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b)
{
    while (len > 0) {
        if (*data == tag && *(data + 1) == len8b && len >= len8b * 8)
            return data + 2;
        len -= (*(data + 1)) * 8;
        data += (*(data + 1)) * 8;
    }
    return NULL;
}
static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac)
{
    struct icmp6hdr *icmphdr = (struct icmp6hdr *)data;
    unsigned char *mac;
    if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) {
        if (len >= 8) {
            mac = scan_tlv(&data[8], len - 8, 1, 1);
            if (mac) {
                RTW_INFO("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
                    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
                    replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
                memcpy(mac, replace_mac, 6);
                return 1;
            }
        }
    } else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) {
        if (len >= 16) {
            mac = scan_tlv(&data[16], len - 16, 1, 1);
            if (mac) {
                RTW_INFO("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
                    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
                    replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
                memcpy(mac, replace_mac, 6);
                return 1;
            }
        }
    } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) {
        if (len >= 24) {
            mac = scan_tlv(&data[24], len - 24, 1, 1);
            if (mac) {
                RTW_INFO("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
                    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
                    replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
                memcpy(mac, replace_mac, 6);
                return 1;
            }
        }
    } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
        if (len >= 24) {
            mac = scan_tlv(&data[24], len - 24, 2, 1);
            if (mac) {
                RTW_INFO("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
                    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
                    replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
                memcpy(mac, replace_mac, 6);
                return 1;
            }
        }
    } else if (icmphdr->icmp6_type == NDISC_REDIRECT) {
        if (len >= 40) {
            mac = scan_tlv(&data[40], len - 40, 2, 1);
            if (mac) {
                RTW_INFO("Redirect,  replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
                    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
                    replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
                memcpy(mac, replace_mac, 6);
                return 1;
            }
        }
    }
    return 0;
}
static void convert_ipv6_mac_to_mc(struct sk_buff *skb)
{
    struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN);
    unsigned char *dst_mac = skb->data;
    /* dst_mac[0] = 0xff; */
    /* dst_mac[1] = 0xff; */
    /*modified by qinjunjie,ipv6 multicast address ix 0x33-33-xx-xx-xx-xx*/
    dst_mac[0] = 0x33;
    dst_mac[1] = 0x33;
    memcpy(&dst_mac[2], &iph->daddr.s6_addr32[3], 4);
#if defined(__LINUX_2_6__)
    /*modified by qinjunjie,warning:should not remove next line*/
    skb->pkt_type = PACKET_MULTICAST;
#endif
}
#endif /* CL_IPV6_PASS */
static __inline__ int __nat25_network_hash(unsigned char *networkAddr)
{
    if (networkAddr[0] == NAT25_IPV4) {
        unsigned long x;
        x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
        return x & (NAT25_HASH_SIZE - 1);
    } else if (networkAddr[0] == NAT25_IPX) {
        unsigned long x;
        x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
            networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
        return x & (NAT25_HASH_SIZE - 1);
    } else if (networkAddr[0] == NAT25_APPLE) {
        unsigned long x;
        x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3];
        return x & (NAT25_HASH_SIZE - 1);
    } else if (networkAddr[0] == NAT25_PPPOE) {
        unsigned long x;
        x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8];
        return x & (NAT25_HASH_SIZE - 1);
    }
#ifdef CL_IPV6_PASS
    else if (networkAddr[0] == NAT25_IPV6) {
        unsigned long x;
        x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
            networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10] ^
            networkAddr[11] ^ networkAddr[12] ^ networkAddr[13] ^ networkAddr[14] ^ networkAddr[15] ^
            networkAddr[16];
        return x & (NAT25_HASH_SIZE - 1);
    }
#endif
    else {
        unsigned long x = 0;
        int i;
        for (i = 0; i < MAX_NETWORK_ADDR_LEN; i++)
            x ^= networkAddr[i];
        return x & (NAT25_HASH_SIZE - 1);
    }
}
static __inline__ void __network_hash_link(_adapter *priv,
        struct nat25_network_db_entry *ent, int hash)
{
    /* Caller must _enter_critical_bh already! */
    /* _irqL irqL; */
    /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */
    ent->next_hash = priv->nethash[hash];
    if (ent->next_hash != NULL)
        ent->next_hash->pprev_hash = &ent->next_hash;
    priv->nethash[hash] = ent;
    ent->pprev_hash = &priv->nethash[hash];
    /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */
}
static __inline__ void __network_hash_unlink(struct nat25_network_db_entry *ent)
{
    /* Caller must _enter_critical_bh already! */
    /* _irqL irqL; */
    /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */
    *(ent->pprev_hash) = ent->next_hash;
    if (ent->next_hash != NULL)
        ent->next_hash->pprev_hash = ent->pprev_hash;
    ent->next_hash = NULL;
    ent->pprev_hash = NULL;
    /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */
}
static int __nat25_db_network_lookup_and_replace(_adapter *priv,
        struct sk_buff *skb, unsigned char *networkAddr)
{
    struct nat25_network_db_entry *db;
    _irqL irqL;
    _enter_critical_bh(&priv->br_ext_lock, &irqL);
    db = priv->nethash[__nat25_network_hash(networkAddr)];
    while (db != NULL) {
        if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
            if (!__nat25_has_expired(priv, db)) {
                /* replace the destination mac address */
                memcpy(skb->data, db->macAddr, ETH_ALEN);
                atomic_inc(&db->use_count);
#ifdef CL_IPV6_PASS
                RTW_INFO("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
                     "%02x%02x%02x%02x%02x%02x\n",
                     db->macAddr[0],
                     db->macAddr[1],
                     db->macAddr[2],
                     db->macAddr[3],
                     db->macAddr[4],
                     db->macAddr[5],
                     db->networkAddr[0],
                     db->networkAddr[1],
                     db->networkAddr[2],
                     db->networkAddr[3],
                     db->networkAddr[4],
                     db->networkAddr[5],
                     db->networkAddr[6],
                     db->networkAddr[7],
                     db->networkAddr[8],
                     db->networkAddr[9],
                     db->networkAddr[10],
                     db->networkAddr[11],
                     db->networkAddr[12],
                     db->networkAddr[13],
                     db->networkAddr[14],
                     db->networkAddr[15],
                     db->networkAddr[16]);
#else
                RTW_INFO("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
                     db->macAddr[0],
                     db->macAddr[1],
                     db->macAddr[2],
                     db->macAddr[3],
                     db->macAddr[4],
                     db->macAddr[5],
                     db->networkAddr[0],
                     db->networkAddr[1],
                     db->networkAddr[2],
                     db->networkAddr[3],
                     db->networkAddr[4],
                     db->networkAddr[5],
                     db->networkAddr[6],
                     db->networkAddr[7],
                     db->networkAddr[8],
                     db->networkAddr[9],
                     db->networkAddr[10]);
#endif
            }
            _exit_critical_bh(&priv->br_ext_lock, &irqL);
            return 1;
        }
        db = db->next_hash;
    }
    _exit_critical_bh(&priv->br_ext_lock, &irqL);
    return 0;
}
static void __nat25_db_network_insert(_adapter *priv,
              unsigned char *macAddr, unsigned char *networkAddr)
{
    struct nat25_network_db_entry *db;
    int hash;
    _irqL irqL;
    _enter_critical_bh(&priv->br_ext_lock, &irqL);
    hash = __nat25_network_hash(networkAddr);
    db = priv->nethash[hash];
    while (db != NULL) {
        if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
            memcpy(db->macAddr, macAddr, ETH_ALEN);
            db->ageing_timer = jiffies;
            _exit_critical_bh(&priv->br_ext_lock, &irqL);
            return;
        }
        db = db->next_hash;
    }
    db = (struct nat25_network_db_entry *) rtw_malloc(sizeof(*db));
    if (db == NULL) {
        _exit_critical_bh(&priv->br_ext_lock, &irqL);
        return;
    }
    memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN);
    memcpy(db->macAddr, macAddr, ETH_ALEN);
    atomic_set(&db->use_count, 1);
    db->ageing_timer = jiffies;
    __network_hash_link(priv, db, hash);
    _exit_critical_bh(&priv->br_ext_lock, &irqL);
}
static void __nat25_db_print(_adapter *priv)
{
    _irqL irqL;
    _enter_critical_bh(&priv->br_ext_lock, &irqL);
#ifdef BR_EXT_DEBUG
    static int counter = 0;
    int i, j;
    struct nat25_network_db_entry *db;
    counter++;
    if ((counter % 16) != 0)
        return;
    for (i = 0, j = 0; i < NAT25_HASH_SIZE; i++) {
        db = priv->nethash[i];
        while (db != NULL) {
#ifdef CL_IPV6_PASS
            panic_printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
                     "%02x%02x%02x%02x%02x%02x\n",
                     j,
                     i,
                     atomic_read(&db->use_count),
                     db->macAddr[0],
                     db->macAddr[1],
                     db->macAddr[2],
                     db->macAddr[3],
                     db->macAddr[4],
                     db->macAddr[5],
                     db->networkAddr[0],
                     db->networkAddr[1],
                     db->networkAddr[2],
                     db->networkAddr[3],
                     db->networkAddr[4],
                     db->networkAddr[5],
                     db->networkAddr[6],
                     db->networkAddr[7],
                     db->networkAddr[8],
                     db->networkAddr[9],
                     db->networkAddr[10],
                     db->networkAddr[11],
                     db->networkAddr[12],
                     db->networkAddr[13],
                     db->networkAddr[14],
                     db->networkAddr[15],
                     db->networkAddr[16]);
#else
            panic_printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
                     j,
                     i,
                     atomic_read(&db->use_count),
                     db->macAddr[0],
                     db->macAddr[1],
                     db->macAddr[2],
                     db->macAddr[3],
                     db->macAddr[4],
                     db->macAddr[5],
                     db->networkAddr[0],
                     db->networkAddr[1],
                     db->networkAddr[2],
                     db->networkAddr[3],
                     db->networkAddr[4],
                     db->networkAddr[5],
                     db->networkAddr[6],
                     db->networkAddr[7],
                     db->networkAddr[8],
                     db->networkAddr[9],
                     db->networkAddr[10]);
#endif
            j++;
            db = db->next_hash;
        }
    }
#endif
    _exit_critical_bh(&priv->br_ext_lock, &irqL);
}
/*
 *    NAT2.5 interface
 */
void nat25_db_cleanup(_adapter *priv)
{
    int i;
    _irqL irqL;
    _enter_critical_bh(&priv->br_ext_lock, &irqL);
    for (i = 0; i < NAT25_HASH_SIZE; i++) {
        struct nat25_network_db_entry *f;
        f = priv->nethash[i];
        while (f != NULL) {
            struct nat25_network_db_entry *g;
            g = f->next_hash;
            if (priv->scdb_entry == f) {
                memset(priv->scdb_mac, 0, ETH_ALEN);
                memset(priv->scdb_ip, 0, 4);
                priv->scdb_entry = NULL;
            }
            __network_hash_unlink(f);
            rtw_mfree((u8 *) f, sizeof(struct nat25_network_db_entry));
            f = g;
        }
    }
    _exit_critical_bh(&priv->br_ext_lock, &irqL);
}
void nat25_db_expire(_adapter *priv)
{
    int i;
    _irqL irqL;
    _enter_critical_bh(&priv->br_ext_lock, &irqL);
    /* if(!priv->ethBrExtInfo.nat25_disable) */
    {
        for (i = 0; i < NAT25_HASH_SIZE; i++) {
            struct nat25_network_db_entry *f;
            f = priv->nethash[i];
            while (f != NULL) {
                struct nat25_network_db_entry *g;
                g = f->next_hash;
                if (__nat25_has_expired(priv, f)) {
                    if (atomic_dec_and_test(&f->use_count)) {
#ifdef BR_EXT_DEBUG
#ifdef CL_IPV6_PASS
                        panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
                            "%02x%02x%02x%02x%02x%02x\n",
                                 i,
                                 f->macAddr[0],
                                 f->macAddr[1],
                                 f->macAddr[2],
                                 f->macAddr[3],
                                 f->macAddr[4],
                                 f->macAddr[5],
                                 f->networkAddr[0],
                                 f->networkAddr[1],
                                 f->networkAddr[2],
                                 f->networkAddr[3],
                                 f->networkAddr[4],
                                 f->networkAddr[5],
                                 f->networkAddr[6],
                                 f->networkAddr[7],
                                 f->networkAddr[8],
                                 f->networkAddr[9],
                                 f->networkAddr[10],
                                 f->networkAddr[11],
                                 f->networkAddr[12],
                                 f->networkAddr[13],
                                 f->networkAddr[14],
                                 f->networkAddr[15],
                            f->networkAddr[16]);
#else
                        panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
                                 i,
                                 f->macAddr[0],
                                 f->macAddr[1],
                                 f->macAddr[2],
                                 f->macAddr[3],
                                 f->macAddr[4],
                                 f->macAddr[5],
                                 f->networkAddr[0],
                                 f->networkAddr[1],
                                 f->networkAddr[2],
                                 f->networkAddr[3],
                                 f->networkAddr[4],
                                 f->networkAddr[5],
                                 f->networkAddr[6],
                                 f->networkAddr[7],
                                 f->networkAddr[8],
                                 f->networkAddr[9],
                            f->networkAddr[10]);
#endif
#endif
                        if (priv->scdb_entry == f) {
                            memset(priv->scdb_mac, 0, ETH_ALEN);
                            memset(priv->scdb_ip, 0, 4);
                            priv->scdb_entry = NULL;
                        }
                        __network_hash_unlink(f);
                        rtw_mfree((u8 *) f, sizeof(struct nat25_network_db_entry));
                    }
                }
                f = g;
            }
        }
    }
    _exit_critical_bh(&priv->br_ext_lock, &irqL);
}
#ifdef SUPPORT_TX_MCAST2UNI
static int checkIPMcAndReplace(_adapter *priv, struct sk_buff *skb, unsigned int *dst_ip)
{
    struct stat_info    *pstat;
    struct list_head    *phead, *plist;
    int i;
    phead = &priv->asoc_list;
    plist = phead->next;
    while (plist != phead) {
        pstat = list_entry(plist, struct stat_info, asoc_list);
        plist = plist->next;
        if (pstat->ipmc_num == 0)
            continue;
        for (i = 0; i < MAX_IP_MC_ENTRY; i++) {
            if (pstat->ipmc[i].used && !memcmp(&pstat->ipmc[i].mcmac[3], ((unsigned char *)dst_ip) + 1, 3)) {
                memcpy(skb->data, pstat->ipmc[i].mcmac, ETH_ALEN);
                return 1;
            }
        }
    }
    return 0;
}
#endif
int nat25_db_handle(_adapter *priv, struct sk_buff *skb, int method)
{
    unsigned short protocol;
    unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
    if (skb == NULL)
        return -1;
    if ((method <= NAT25_MIN) || (method >= NAT25_MAX))
        return -1;
    protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN));
    /*---------------------------------------------------*/
    /*                 Handle IP frame                  */
    /*---------------------------------------------------*/
    if (protocol == __constant_htons(ETH_P_IP)) {
        struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN);
        if (((unsigned char *)(iph) + (iph->ihl << 2)) >= (skb->data + ETH_HLEN + skb->len)) {
            DEBUG_WARN("NAT25: malformed IP packet !\n");
            return -1;
        }
        switch (method) {
        case NAT25_CHECK:
            return -1;
        case NAT25_INSERT: {
            /* some muticast with source IP is all zero, maybe other case is illegal */
            /* in class A, B, C, host address is all zero or all one is illegal */
            if (iph->saddr == 0)
                return 0;
            RTW_INFO("NAT25: Insert IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr);
            __nat25_generate_ipv4_network_addr(networkAddr, &iph->saddr);
            /* record source IP address and , source mac address into db */
            __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr);
            __nat25_db_print(priv);
        }
        return 0;
        case NAT25_LOOKUP: {
            RTW_INFO("NAT25: Lookup IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr);
#ifdef SUPPORT_TX_MCAST2UNI
            if (priv->pshare->rf_ft_var.mc2u_disable ||
                ((((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE))
                   == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) &&
                  !checkIPMcAndReplace(priv, skb, &iph->daddr)) ||
                 (OPMODE & WIFI_ADHOC_STATE)))
#endif
            {
                __nat25_generate_ipv4_network_addr(networkAddr, &iph->daddr);
                if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) {
                    if (*((unsigned char *)&iph->daddr + 3) == 0xff) {
                        /* L2 is unicast but L3 is broadcast, make L2 bacome broadcast */
                        RTW_INFO("NAT25: Set DA as boardcast\n");
                        memset(skb->data, 0xff, ETH_ALEN);
                    } else {
                        /* forward unknow IP packet to upper TCP/IP */
                        RTW_INFO("NAT25: Replace DA with BR's MAC\n");
                        if ((*(u32 *)priv->br_mac) == 0 && (*(u16 *)(priv->br_mac + 4)) == 0) {
                            void netdev_br_init(struct net_device *netdev);
                            printk("Re-init netdev_br_init() due to br_mac==0!\n");
                            netdev_br_init(priv->pnetdev);
                        }
                        memcpy(skb->data, priv->br_mac, ETH_ALEN);
                    }
                }
            }
        }
        return 0;
        default:
            return -1;
        }
    }
    /*---------------------------------------------------*/
    /*                 Handle ARP frame                 */
    /*---------------------------------------------------*/
    else if (protocol == __constant_htons(ETH_P_ARP)) {
        struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN);
        unsigned char *arp_ptr = (unsigned char *)(arp + 1);
        unsigned int *sender, *target;
        if (arp->ar_pro != __constant_htons(ETH_P_IP)) {
            DEBUG_WARN("NAT25: arp protocol unknown (%4x)!\n", htons(arp->ar_pro));
            return -1;
        }
        switch (method) {
        case NAT25_CHECK:
            return 0;    /* skb_copy for all ARP frame */
        case NAT25_INSERT: {
            RTW_INFO("NAT25: Insert ARP, MAC=%02x%02x%02x%02x%02x%02x\n", arp_ptr[0],
                arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]);
            /* change to ARP sender mac address to wlan STA address */
            memcpy(arp_ptr, GET_MY_HWADDR(priv), ETH_ALEN);
            arp_ptr += arp->ar_hln;
            sender = (unsigned int *)arp_ptr;
            __nat25_generate_ipv4_network_addr(networkAddr, sender);
            __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr);
            __nat25_db_print(priv);
        }
        return 0;
        case NAT25_LOOKUP: {
            RTW_INFO("NAT25: Lookup ARP\n");
            arp_ptr += arp->ar_hln;
            sender = (unsigned int *)arp_ptr;
            arp_ptr += (arp->ar_hln + arp->ar_pln);
            target = (unsigned int *)arp_ptr;
            __nat25_generate_ipv4_network_addr(networkAddr, target);
            __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
            /* change to ARP target mac address to Lookup result */
            arp_ptr = (unsigned char *)(arp + 1);
            arp_ptr += (arp->ar_hln + arp->ar_pln);
            memcpy(arp_ptr, skb->data, ETH_ALEN);
        }
        return 0;
        default:
            return -1;
        }
    }
    /*---------------------------------------------------*/
    /*         Handle IPX and Apple Talk frame          */
    /*---------------------------------------------------*/
    else if ((protocol == __constant_htons(ETH_P_IPX)) ||
         (protocol == __constant_htons(ETH_P_ATALK)) ||
         (protocol == __constant_htons(ETH_P_AARP))) {
        unsigned char ipx_header[2] = {0xFF, 0xFF};
        struct ipxhdr    *ipx = NULL;
        struct elapaarp    *ea = NULL;
        struct ddpehdr    *ddp = NULL;
        unsigned char *framePtr = skb->data + ETH_HLEN;
        if (protocol == __constant_htons(ETH_P_IPX)) {
            RTW_INFO("NAT25: Protocol=IPX (Ethernet II)\n");
            ipx = (struct ipxhdr *)framePtr;
        } else { /* if(protocol <= __constant_htons(ETH_FRAME_LEN)) */
            if (!memcmp(ipx_header, framePtr, 2)) {
                RTW_INFO("NAT25: Protocol=IPX (Ethernet 802.3)\n");
                ipx = (struct ipxhdr *)framePtr;
            } else {
                unsigned char ipx_8022_type =  0xE0;
                unsigned char snap_8022_type = 0xAA;
                if (*framePtr == snap_8022_type) {
                    unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81, 0x37};        /* IPX SNAP ID */
                    unsigned char aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3};    /* Apple Talk AARP SNAP ID */
                    unsigned char ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B};    /* Apple Talk DDP SNAP ID */
                    framePtr += 3;    /* eliminate the 802.2 header */
                    if (!memcmp(ipx_snap_id, framePtr, 5)) {
                        framePtr += 5;    /* eliminate the SNAP header */
                        RTW_INFO("NAT25: Protocol=IPX (Ethernet SNAP)\n");
                        ipx = (struct ipxhdr *)framePtr;
                    } else if (!memcmp(aarp_snap_id, framePtr, 5)) {
                        framePtr += 5;    /* eliminate the SNAP header */
                        ea = (struct elapaarp *)framePtr;
                    } else if (!memcmp(ddp_snap_id, framePtr, 5)) {
                        framePtr += 5;    /* eliminate the SNAP header */
                        ddp = (struct ddpehdr *)framePtr;
                    } else {
                        DEBUG_WARN("NAT25: Protocol=Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0],
                            framePtr[1], framePtr[2], framePtr[3], framePtr[4]);
                        return -1;
                    }
                } else if (*framePtr == ipx_8022_type) {
                    framePtr += 3;    /* eliminate the 802.2 header */
                    if (!memcmp(ipx_header, framePtr, 2)) {
                        RTW_INFO("NAT25: Protocol=IPX (Ethernet 802.2)\n");
                        ipx = (struct ipxhdr *)framePtr;
                    } else
                        return -1;
                }
            }
        }
        /*   IPX  */
        if (ipx != NULL) {
            switch (method) {
            case NAT25_CHECK:
                if (!memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) {
                    RTW_INFO("NAT25: Check IPX skb_copy\n");
                    return 0;
                }
                return -1;
            case NAT25_INSERT: {
                RTW_INFO("NAT25: Insert IPX, Dest=%08x,%02x%02x%02x%02x%02x%02x,%04x Source=%08x,%02x%02x%02x%02x%02x%02x,%04x\n",
                     ipx->ipx_dest.net,
                     ipx->ipx_dest.node[0],
                     ipx->ipx_dest.node[1],
                     ipx->ipx_dest.node[2],
                     ipx->ipx_dest.node[3],
                     ipx->ipx_dest.node[4],
                     ipx->ipx_dest.node[5],
                     ipx->ipx_dest.sock,
                     ipx->ipx_source.net,
                     ipx->ipx_source.node[0],
                     ipx->ipx_source.node[1],
                     ipx->ipx_source.node[2],
                     ipx->ipx_source.node[3],
                     ipx->ipx_source.node[4],
                     ipx->ipx_source.node[5],
                     ipx->ipx_source.sock);
                if (!memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) {
                    RTW_INFO("NAT25: Use IPX Net, and Socket as network addr\n");
                    __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock);
                    /* change IPX source node addr to wlan STA address */
                    memcpy(ipx->ipx_source.node, GET_MY_HWADDR(priv), ETH_ALEN);
                } else
                    __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node);
                __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr);
                __nat25_db_print(priv);
            }
            return 0;
            case NAT25_LOOKUP: {
                if (!memcmp(GET_MY_HWADDR(priv), ipx->ipx_dest.node, ETH_ALEN)) {
                    RTW_INFO("NAT25: Lookup IPX, Modify Destination IPX Node addr\n");
                    __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock);
                    __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
                    /* replace IPX destination node addr with Lookup destination MAC addr */
                    memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN);
                } else {
                    __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node);
                    __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
                }
            }
            return 0;
            default:
                return -1;
            }
        }
        /*   AARP  */
        else if (ea != NULL) {
            /* Sanity check fields. */
            if (ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN) {
                DEBUG_WARN("NAT25: Appletalk AARP Sanity check fail!\n");
                return -1;
            }
            switch (method) {
            case NAT25_CHECK:
                return 0;
            case NAT25_INSERT: {
                /* change to AARP source mac address to wlan STA address */
                memcpy(ea->hw_src, GET_MY_HWADDR(priv), ETH_ALEN);
                RTW_INFO("NAT25: Insert AARP, Source=%d,%d Destination=%d,%d\n",
                     ea->pa_src_net,
                     ea->pa_src_node,
                     ea->pa_dst_net,
                     ea->pa_dst_node);
                __nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node);
                __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr);
                __nat25_db_print(priv);
            }
            return 0;
            case NAT25_LOOKUP: {
                RTW_INFO("NAT25: Lookup AARP, Source=%d,%d Destination=%d,%d\n",
                     ea->pa_src_net,
                     ea->pa_src_node,
                     ea->pa_dst_net,
                     ea->pa_dst_node);
                __nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node);
                __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
                /* change to AARP destination mac address to Lookup result */
                memcpy(ea->hw_dst, skb->data, ETH_ALEN);
            }
            return 0;
            default:
                return -1;
            }
        }
        /*   DDP  */
        else if (ddp != NULL) {
            switch (method) {
            case NAT25_CHECK:
                return -1;
            case NAT25_INSERT: {
                RTW_INFO("NAT25: Insert DDP, Source=%d,%d Destination=%d,%d\n",
                     ddp->deh_snet,
                     ddp->deh_snode,
                     ddp->deh_dnet,
                     ddp->deh_dnode);
                __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode);
                __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr);
                __nat25_db_print(priv);
            }
            return 0;
            case NAT25_LOOKUP: {
                RTW_INFO("NAT25: Lookup DDP, Source=%d,%d Destination=%d,%d\n",
                     ddp->deh_snet,
                     ddp->deh_snode,
                     ddp->deh_dnet,
                     ddp->deh_dnode);
                __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode);
                __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
            }
            return 0;
            default:
                return -1;
            }
        }
        return -1;
    }
    /*---------------------------------------------------*/
    /*                Handle PPPoE frame                */
    /*---------------------------------------------------*/
    else if ((protocol == __constant_htons(ETH_P_PPP_DISC)) ||
         (protocol == __constant_htons(ETH_P_PPP_SES))) {
        struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
        unsigned short *pMagic;
        switch (method) {
        case NAT25_CHECK:
            if (ph->sid == 0)
                return 0;
            return 1;
        case NAT25_INSERT:
            if (ph->sid == 0) {    /* Discovery phase according to tag */
                if (ph->code == PADI_CODE || ph->code == PADR_CODE) {
                    if (priv->ethBrExtInfo.addPPPoETag) {
                        struct pppoe_tag *tag, *pOldTag;
                        unsigned char tag_buf[40];
                        int old_tag_len = 0;
                        tag = (struct pppoe_tag *)tag_buf;
                        pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID));
                        if (pOldTag) { /* if SID existed, copy old value and delete it */
                            old_tag_len = ntohs(pOldTag->tag_len);
                            if (old_tag_len + TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN > sizeof(tag_buf)) {
                                DEBUG_ERR("SID tag length too long!\n");
                                return -1;
                            }
                            memcpy(tag->tag_data + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN,
                                   pOldTag->tag_data, old_tag_len);
                            if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN + old_tag_len) < 0) {
                                DEBUG_ERR("call skb_pull_and_merge() failed in PADI/R packet!\n");
                                return -1;
                            }
                            ph->length = htons(ntohs(ph->length) - TAG_HDR_LEN - old_tag_len);
                        }
                        tag->tag_type = PTT_RELAY_SID;
                        tag->tag_len = htons(MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN + old_tag_len);
                        /* insert the magic_code+client mac in relay tag */
                        pMagic = (unsigned short *)tag->tag_data;
                        *pMagic = htons(MAGIC_CODE);
                        memcpy(tag->tag_data + MAGIC_CODE_LEN, skb->data + ETH_ALEN, ETH_ALEN);
                        /* Add relay tag */
                        if (__nat25_add_pppoe_tag(skb, tag) < 0)
                            return -1;
                        RTW_INFO("NAT25: Insert PPPoE, forward %s packet\n",
                            (ph->code == PADI_CODE ? "PADI" : "PADR"));
                    } else { /* not add relay tag */
                        if (priv->pppoe_connection_in_progress &&
                            memcmp(skb->data + ETH_ALEN, priv->pppoe_addr, ETH_ALEN))     {
                            DEBUG_ERR("Discard PPPoE packet due to another PPPoE connection is in progress!\n");
                            return -2;
                        }
                        if (priv->pppoe_connection_in_progress == 0)
                            memcpy(priv->pppoe_addr, skb->data + ETH_ALEN, ETH_ALEN);
                        priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
                    }
                } else
                    return -1;
            } else {    /* session phase */
                RTW_INFO("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name);
                __nat25_generate_pppoe_network_addr(networkAddr, skb->data, &(ph->sid));
                __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr);
                __nat25_db_print(priv);
                if (!priv->ethBrExtInfo.addPPPoETag &&
                    priv->pppoe_connection_in_progress &&
                    !memcmp(skb->data + ETH_ALEN, priv->pppoe_addr, ETH_ALEN))
                    priv->pppoe_connection_in_progress = 0;
            }
            return 0;
        case NAT25_LOOKUP:
            if (ph->code == PADO_CODE || ph->code == PADS_CODE) {
                if (priv->ethBrExtInfo.addPPPoETag) {
                    struct pppoe_tag *tag;
                    unsigned char *ptr;
                    unsigned short tagType, tagLen;
                    int offset = 0;
                    ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID));
                    if (ptr == 0) {
                        DEBUG_ERR("Fail to find PTT_RELAY_SID in FADO!\n");
                        return -1;
                    }
                    tag = (struct pppoe_tag *)ptr;
                    tagType = (unsigned short)((ptr[0] << 8) + ptr[1]);
                    tagLen = (unsigned short)((ptr[2] << 8) + ptr[3]);
                    if ((tagType != ntohs(PTT_RELAY_SID)) || (tagLen < (MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN))) {
                        DEBUG_ERR("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen);
                        return -1;
                    }
                    pMagic = (unsigned short *)tag->tag_data;
                    if (ntohs(*pMagic) != MAGIC_CODE) {
                        DEBUG_ERR("Can't find MAGIC_CODE in %s packet!\n",
                            (ph->code == PADO_CODE ? "PADO" : "PADS"));
                        return -1;
                    }
                    memcpy(skb->data, tag->tag_data + MAGIC_CODE_LEN, ETH_ALEN);
                    if (tagLen > MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN)
                        offset = TAG_HDR_LEN;
                    if (skb_pull_and_merge(skb, ptr + offset, TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN - offset) < 0) {
                        DEBUG_ERR("call skb_pull_and_merge() failed in PADO packet!\n");
                        return -1;
                    }
                    ph->length = htons(ntohs(ph->length) - (TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN - offset));
                    if (offset > 0)
                        tag->tag_len = htons(tagLen - MAGIC_CODE_LEN - RTL_RELAY_TAG_LEN);
                    RTW_INFO("NAT25: Lookup PPPoE, forward %s Packet from %s\n",
                        (ph->code == PADO_CODE ? "PADO" : "PADS"),    skb->dev->name);
                } else { /* not add relay tag */
                    if (!priv->pppoe_connection_in_progress) {
                        DEBUG_ERR("Discard PPPoE packet due to no connection in progresss!\n");
                        return -1;
                    }
                    memcpy(skb->data, priv->pppoe_addr, ETH_ALEN);
                    priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
                }
            } else {
                if (ph->sid != 0) {
                    RTW_INFO("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb->dev->name);
                    __nat25_generate_pppoe_network_addr(networkAddr, skb->data + ETH_ALEN, &(ph->sid));
                    __nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
                    __nat25_db_print(priv);
                } else
                    return -1;
            }
            return 0;
        default:
            return -1;
        }
    }
    /*---------------------------------------------------*/
    /*                 Handle EAP frame                 */
    /*---------------------------------------------------*/
    else if (protocol == __constant_htons(0x888e)) {
        switch (method) {
        case NAT25_CHECK:
            return -1;
        case NAT25_INSERT:
            return 0;
        case NAT25_LOOKUP:
            return 0;
        default:
            return -1;
        }
    }
    /*---------------------------------------------------*/
    /*         Handle C-Media proprietary frame         */
    /*---------------------------------------------------*/
    else if ((protocol == __constant_htons(0xe2ae)) ||
         (protocol == __constant_htons(0xe2af))) {
        switch (method) {
        case NAT25_CHECK:
            return -1;
        case NAT25_INSERT:
            return 0;
        case NAT25_LOOKUP:
            return 0;
        default:
            return -1;
        }
    }
    /*---------------------------------------------------*/
    /*         Handle IPV6 frame                                   */
    /*---------------------------------------------------*/
#ifdef CL_IPV6_PASS
    else if (protocol == __constant_htons(ETH_P_IPV6)) {
        struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN);
        if (sizeof(*iph) >= (skb->len - ETH_HLEN)) {
            DEBUG_WARN("NAT25: malformed IPv6 packet !\n");
            return -1;
        }
        switch (method) {
        case NAT25_CHECK:
            if (skb->data[0] & 1)
                return 0;
            return -1;
        case NAT25_INSERT: {
            RTW_INFO("NAT25: Insert IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x,"
                " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n",
                iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3],
                iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7],
                iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3],
                iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]);
            if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) {
                __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->saddr);
                __nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr);
                __nat25_db_print(priv);
                if (iph->nexthdr == IPPROTO_ICMPV6 &&
                    skb->len > (ETH_HLEN +  sizeof(*iph) + 4)) {
                    if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph),
                        skb->len - ETH_HLEN - sizeof(*iph), GET_MY_HWADDR(priv))) {
                        struct icmp6hdr  *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph));
                        hdr->icmp6_cksum = 0;
                        hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr,
                            iph->payload_len,
                            IPPROTO_ICMPV6,
                            csum_partial((__u8 *)hdr, iph->payload_len, 0));
                    }
                }
            }
        }
        return 0;
        case NAT25_LOOKUP:
            RTW_INFO("NAT25: Lookup IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x,"
                 " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n",
                iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3],
                iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7],
                iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3],
                iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]);
            __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->daddr);
            if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) {
#ifdef SUPPORT_RX_UNI2MCAST
                if (iph->daddr.s6_addr[0] == 0xff)
                    convert_ipv6_mac_to_mc(skb);
#endif
            }
            return 0;
        default:
            return -1;
        }
    }
#endif /* CL_IPV6_PASS */
    return -1;
}
int nat25_handle_frame(_adapter *priv, struct sk_buff *skb)
{
#ifdef BR_EXT_DEBUG
    if ((!priv->ethBrExtInfo.nat25_disable) && (!(skb->data[0] & 1))) {
        panic_printk("NAT25: Input Frame: DA=%02x%02x%02x%02x%02x%02x SA=%02x%02x%02x%02x%02x%02x\n",
                 skb->data[0],
                 skb->data[1],
                 skb->data[2],
                 skb->data[3],
                 skb->data[4],
                 skb->data[5],
                 skb->data[6],
                 skb->data[7],
                 skb->data[8],
                 skb->data[9],
                 skb->data[10],
                 skb->data[11]);
    }
#endif
    if (!(skb->data[0] & 1)) {
        int is_vlan_tag = 0, i, retval = 0;
        unsigned short vlan_hdr = 0;
        if (*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_8021Q)) {
            is_vlan_tag = 1;
            vlan_hdr = *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2));
            for (i = 0; i < 6; i++)
                *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + ETH_ALEN * 2 - 2 - i * 2));
            skb_pull(skb, 4);
        }
        if (!priv->ethBrExtInfo.nat25_disable) {
            _irqL irqL;
            _enter_critical_bh(&priv->br_ext_lock, &irqL);
            /*
             *    This function look up the destination network address from
             *    the NAT2.5 database. Return value = -1 means that the
             *    corresponding network protocol is NOT support.
             */
            if (!priv->ethBrExtInfo.nat25sc_disable &&
                (*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_IP)) &&
                !memcmp(priv->scdb_ip, skb->data + ETH_HLEN + 16, 4)) {
                memcpy(skb->data, priv->scdb_mac, ETH_ALEN);
                _exit_critical_bh(&priv->br_ext_lock, &irqL);
            } else {
                _exit_critical_bh(&priv->br_ext_lock, &irqL);
                retval = nat25_db_handle(priv, skb, NAT25_LOOKUP);
            }
        } else {
            if (((*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_IP)) &&
                 !memcmp(priv->br_ip, skb->data + ETH_HLEN + 16, 4)) ||
                ((*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_ARP)) &&
                 !memcmp(priv->br_ip, skb->data + ETH_HLEN + 24, 4))) {
                /* for traffic to upper TCP/IP */
                retval = nat25_db_handle(priv, skb, NAT25_LOOKUP);
            }
        }
        if (is_vlan_tag) {
            skb_push(skb, 4);
            for (i = 0; i < 6; i++)
                *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2));
            *((unsigned short *)(skb->data + ETH_ALEN * 2)) = __constant_htons(ETH_P_8021Q);
            *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)) = vlan_hdr;
        }
        if (retval == -1) {
            /* DEBUG_ERR("NAT25: Lookup fail!\n"); */
            return -1;
        }
    }
    return 0;
}
#if 0
void mac_clone(_adapter *priv, unsigned char *addr)
{
    struct sockaddr sa;
    memcpy(sa.sa_data, addr, ETH_ALEN);
    RTW_INFO("MAC Clone: Addr=%02x%02x%02x%02x%02x%02x\n",
         addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
    rtl8192cd_set_hwaddr(priv->dev, &sa);
}
int mac_clone_handle_frame(_adapter *priv, struct sk_buff *skb)
{
    if (priv->ethBrExtInfo.macclone_enable && !priv->macclone_completed) {
        if (!(skb->data[ETH_ALEN] & 1)) {    /* check any other particular MAC add */
            if (memcmp(skb->data + ETH_ALEN, GET_MY_HWADDR(priv), ETH_ALEN) &&
                ((priv->dev->br_port) &&
                 memcmp(skb->data + ETH_ALEN, priv->br_mac, ETH_ALEN))) {
                mac_clone(priv, skb->data + ETH_ALEN);
                priv->macclone_completed = 1;
            }
        }
    }
    return 0;
}
#endif /* 0 */
#define SERVER_PORT            67
#define CLIENT_PORT            68
#define DHCP_MAGIC            0x63825363
#define BROADCAST_FLAG        0x8000
struct dhcpMessage {
    u_int8_t op;
    u_int8_t htype;
    u_int8_t hlen;
    u_int8_t hops;
    u_int32_t xid;
    u_int16_t secs;
    u_int16_t flags;
    u_int32_t ciaddr;
    u_int32_t yiaddr;
    u_int32_t siaddr;
    u_int32_t giaddr;
    u_int8_t chaddr[16];
    u_int8_t sname[64];
    u_int8_t file[128];
    u_int32_t cookie;
    u_int8_t options[308]; /* 312 - cookie */
};
void dhcp_flag_bcast(_adapter *priv, struct sk_buff *skb)
{
    if (skb == NULL)
        return;
    if (!priv->ethBrExtInfo.dhcp_bcst_disable) {
        unsigned short protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN));
        if (protocol == __constant_htons(ETH_P_IP)) { /* IP */
            struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN);
            if (iph->protocol == IPPROTO_UDP) { /* UDP */
                struct udphdr *udph = (struct udphdr *)((SIZE_PTR)iph + (iph->ihl << 2));
                if ((udph->source == __constant_htons(CLIENT_PORT))
                    && (udph->dest == __constant_htons(SERVER_PORT))) { /* DHCP request */
                    struct dhcpMessage *dhcph =
                        (struct dhcpMessage *)((SIZE_PTR)udph + sizeof(struct udphdr));
                    if (dhcph->cookie == __constant_htonl(DHCP_MAGIC)) { /* match magic word */
                        if (!(dhcph->flags & htons(BROADCAST_FLAG))) { /* if not broadcast */
                            register int sum = 0;
                            RTW_INFO("DHCP: change flag of DHCP request to broadcast.\n");
                            /* or BROADCAST flag */
                            dhcph->flags |= htons(BROADCAST_FLAG);
                            /* recalculate checksum */
                            sum = ~(udph->check) & 0xffff;
                            sum += dhcph->flags;
                            while (sum >> 16)
                                sum = (sum & 0xffff) + (sum >> 16);
                            udph->check = ~sum;
                        }
                    }
                }
            }
        }
    }
}
void *scdb_findEntry(_adapter *priv, unsigned char *macAddr,
             unsigned char *ipAddr)
{
    unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
    struct nat25_network_db_entry *db;
    int hash;
    /* _irqL irqL; */
    /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */
    __nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr);
    hash = __nat25_network_hash(networkAddr);
    db = priv->nethash[hash];
    while (db != NULL) {
        if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
            /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */
            return (void *)db;
        }
        db = db->next_hash;
    }
    /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */
    return NULL;
}
#endif /* CONFIG_BR_EXT */
linux-bsp/drivers/rtl8188eus/core/rtw_bt_mp.c
New file
@@ -0,0 +1,1580 @@
/******************************************************************************
 *
 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 *
 ******************************************************************************/
#include <drv_types.h>
#include <rtw_bt_mp.h>
#if defined(CONFIG_RTL8723B)
    #include <rtl8723b_hal.h>
#endif
#if defined(CONFIG_RTL8723B) || defined(CONFIG_RTL8821A)
void MPh2c_timeout_handle(void *FunctionContext)
{
    PADAPTER pAdapter;
    PMPT_CONTEXT pMptCtx;
    RTW_INFO("[MPT], MPh2c_timeout_handle\n");
    pAdapter = (PADAPTER)FunctionContext;
    pMptCtx = &pAdapter->mppriv.mpt_ctx;
    pMptCtx->bMPh2c_timeout = _TRUE;
    if ((_FALSE == pMptCtx->MptH2cRspEvent)
        || ((_TRUE == pMptCtx->MptH2cRspEvent)
        && (_FALSE == pMptCtx->MptBtC2hEvent)))
        _rtw_up_sema(&pMptCtx->MPh2c_Sema);
}
u32 WaitC2Hevent(PADAPTER pAdapter, u8 *C2H_event, u32 delay_time)
{
    PMPT_CONTEXT        pMptCtx = &(pAdapter->mppriv.mpt_ctx);
    pMptCtx->bMPh2c_timeout = _FALSE;
    if (pAdapter->registrypriv.mp_mode == 0) {
        RTW_INFO("[MPT], Error!! WaitC2Hevent mp_mode == 0!!\n");
        return _FALSE;
    }
    _set_timer(&pMptCtx->MPh2c_timeout_timer, delay_time);
    _rtw_down_sema(&pMptCtx->MPh2c_Sema);
    if (pMptCtx->bMPh2c_timeout == _TRUE) {
        *C2H_event = _FALSE;
        return _FALSE;
    }
    /* for safty, cancel timer here again */
    _cancel_timer_ex(&pMptCtx->MPh2c_timeout_timer);
    return _TRUE;
}
BT_CTRL_STATUS
mptbt_CheckC2hFrame(
    PADAPTER        Adapter,
    PBT_H2C            pH2c,
    PBT_EXT_C2H        pExtC2h
)
{
    BT_CTRL_STATUS    c2hStatus = BT_STATUS_C2H_SUCCESS;
    /* RTW_INFO("[MPT], MPT rsp C2H hex: %x %x %x  %x %x %x\n"), pExtC2h , pExtC2h+1 ,pExtC2h+2 ,pExtC2h+3 ,pExtC2h+4 ,pExtC2h+5); */
    RTW_INFO("[MPT], statusCode = 0x%x\n", pExtC2h->statusCode);
    RTW_INFO("[MPT], retLen = %d\n", pExtC2h->retLen);
    RTW_INFO("[MPT], opCodeVer : req/rsp=%d/%d\n", pH2c->opCodeVer, pExtC2h->opCodeVer);
    RTW_INFO("[MPT], reqNum : req/rsp=%d/%d\n", pH2c->reqNum, pExtC2h->reqNum);
    if (pExtC2h->reqNum != pH2c->reqNum) {
        c2hStatus = BT_STATUS_C2H_REQNUM_MISMATCH;
        RTW_INFO("[MPT], Error!! C2H reqNum Mismatch!!\n");
    } else if (pExtC2h->opCodeVer != pH2c->opCodeVer) {
        c2hStatus = BT_STATUS_OPCODE_L_VERSION_MISMATCH;
        RTW_INFO("[MPT], Error!! OPCode version L mismatch!!\n");
    }
    return c2hStatus;
}
BT_CTRL_STATUS
mptbt_SendH2c(
    PADAPTER    Adapter,
    PBT_H2C    pH2c,
    u2Byte        h2cCmdLen
)
{
    /* KIRQL                OldIrql = KeGetCurrentIrql(); */
    BT_CTRL_STATUS    h2cStatus = BT_STATUS_H2C_SUCCESS;
    PMPT_CONTEXT        pMptCtx = &(Adapter->mppriv.mpt_ctx);
    u1Byte                i;
    RTW_INFO("[MPT], mptbt_SendH2c()=========>\n");
    /* PlatformResetEvent(&pMptCtx->MptH2cRspEvent); */
    /* PlatformResetEvent(&pMptCtx->MptBtC2hEvent); */
    /*    if(OldIrql == PASSIVE_LEVEL)
     *    { */
    /* RTPRINT_DATA(FMPBT, FMPBT_H2C_CONTENT, ("[MPT], MPT H2C hex:\n"), pH2c, h2cCmdLen); */
    for (i = 0; i < BT_H2C_MAX_RETRY; i++) {
        RTW_INFO("[MPT], Send H2C command to wifi!!!\n");
        pMptCtx->MptH2cRspEvent = _FALSE;
        pMptCtx->MptBtC2hEvent = _FALSE;
#if defined(CONFIG_RTL8723B)
        rtl8723b_set_FwBtMpOper_cmd(Adapter, pH2c->opCode, pH2c->opCodeVer, pH2c->reqNum, pH2c->buf);
#endif
        pMptCtx->h2cReqNum++;
        pMptCtx->h2cReqNum %= 16;
        if (WaitC2Hevent(Adapter, &pMptCtx->MptH2cRspEvent, 100)) {
            RTW_INFO("[MPT], Received WiFi MptH2cRspEvent!!!\n");
            if (WaitC2Hevent(Adapter, &pMptCtx->MptBtC2hEvent, 400)) {
                RTW_INFO("[MPT], Received MptBtC2hEvent!!!\n");
                break;
            } else {
                RTW_INFO("[MPT], Error!!BT MptBtC2hEvent timeout!!\n");
                h2cStatus = BT_STATUS_H2C_BT_NO_RSP;
            }
        } else {
            RTW_INFO("[MPT], Error!!WiFi  MptH2cRspEvent timeout!!\n");
            h2cStatus = BT_STATUS_H2C_TIMTOUT;
        }
    }
    /*    }
     *    else
     *    {
     *         RT_ASSERT(FALSE, ("[MPT],  mptbt_SendH2c() can only run under PASSIVE_LEVEL!!\n"));
     *        h2cStatus = BT_STATUS_WRONG_LEVEL;
     *    } */
    RTW_INFO("[MPT], mptbt_SendH2c()<=========\n");
    return h2cStatus;
}
BT_CTRL_STATUS
mptbt_CheckBtRspStatus(
    PADAPTER            Adapter,
    PBT_EXT_C2H            pExtC2h
)
{
    BT_CTRL_STATUS    retStatus = BT_OP_STATUS_SUCCESS;
    switch (pExtC2h->statusCode) {
    case BT_OP_STATUS_SUCCESS:
        retStatus = BT_STATUS_BT_OP_SUCCESS;
        RTW_INFO("[MPT], BT status : BT_STATUS_SUCCESS\n");
        break;
    case BT_OP_STATUS_VERSION_MISMATCH:
        retStatus = BT_STATUS_OPCODE_L_VERSION_MISMATCH;
        RTW_INFO("[MPT], BT status : BT_STATUS_OPCODE_L_VERSION_MISMATCH\n");
        break;
    case BT_OP_STATUS_UNKNOWN_OPCODE:
        retStatus = BT_STATUS_UNKNOWN_OPCODE_L;
        RTW_INFO("[MPT], BT status : BT_STATUS_UNKNOWN_OPCODE_L\n");
        break;
    case BT_OP_STATUS_ERROR_PARAMETER:
        retStatus = BT_STATUS_PARAMETER_FORMAT_ERROR_L;
        RTW_INFO("[MPT], BT status : BT_STATUS_PARAMETER_FORMAT_ERROR_L\n");
        break;
    default:
        retStatus = BT_STATUS_UNKNOWN_STATUS_L;
        RTW_INFO("[MPT], BT status : BT_STATUS_UNKNOWN_STATUS_L\n");
        break;
    }
    return retStatus;
}
BT_CTRL_STATUS
mptbt_BtFwOpCodeProcess(
    PADAPTER        Adapter,
    u1Byte            btFwOpCode,
    u1Byte            opCodeVer,
    pu1Byte            pH2cPar,
    u1Byte            h2cParaLen
)
{
    u1Byte                H2C_Parameter[6] = {0};
    PBT_H2C                pH2c = (PBT_H2C)&H2C_Parameter[0];
    PMPT_CONTEXT        pMptCtx = &(Adapter->mppriv.mpt_ctx);
    PBT_EXT_C2H            pExtC2h = (PBT_EXT_C2H)&pMptCtx->c2hBuf[0];
    u2Byte                paraLen = 0, i;
    BT_CTRL_STATUS    h2cStatus = BT_STATUS_H2C_SUCCESS, c2hStatus = BT_STATUS_C2H_SUCCESS;
    BT_CTRL_STATUS    retStatus = BT_STATUS_H2C_BT_NO_RSP;
    if (Adapter->registrypriv.mp_mode == 0) {
        RTW_INFO("[MPT], Error!! mptbt_BtFwOpCodeProces mp_mode == 0!!\n");
        return _FALSE;
    }
    pH2c->opCode = btFwOpCode;
    pH2c->opCodeVer = opCodeVer;
    pH2c->reqNum = pMptCtx->h2cReqNum;
    /* PlatformMoveMemory(&pH2c->buf[0], pH2cPar, h2cParaLen); */
    /* _rtw_memcpy(&pH2c->buf[0], pH2cPar, h2cParaLen); */
    _rtw_memcpy(pH2c->buf, pH2cPar, h2cParaLen);
    RTW_INFO("[MPT], pH2c->opCode=%d\n", pH2c->opCode);
    RTW_INFO("[MPT], pH2c->opCodeVer=%d\n", pH2c->opCodeVer);
    RTW_INFO("[MPT], pH2c->reqNum=%d\n", pH2c->reqNum);
    RTW_INFO("[MPT], h2c parameter length=%d\n", h2cParaLen);
    for (i = 0; i < h2cParaLen; i++)
        RTW_INFO("[MPT], parameter[%d]=0x%02x\n", i, pH2c->buf[i]);
    h2cStatus = mptbt_SendH2c(Adapter, pH2c, h2cParaLen + 2);
    if (BT_STATUS_H2C_SUCCESS == h2cStatus) {
        /* if reach here, it means H2C get the correct c2h response, */
        c2hStatus = mptbt_CheckC2hFrame(Adapter, pH2c, pExtC2h);
        if (BT_STATUS_C2H_SUCCESS == c2hStatus)
            retStatus = mptbt_CheckBtRspStatus(Adapter, pExtC2h);
        else {
            RTW_INFO("[MPT], Error!! C2H failed for pH2c->opCode=%d\n", pH2c->opCode);
            /* check c2h status error, return error status code to upper layer. */
            retStatus = c2hStatus;
        }
    } else {
        RTW_INFO("[MPT], Error!! H2C failed for pH2c->opCode=%d\n", pH2c->opCode);
        /* check h2c status error, return error status code to upper layer. */
        retStatus = h2cStatus;
    }
    return retStatus;
}
u2Byte
mptbt_BtReady(
    PADAPTER        Adapter,
    PBT_REQ_CMD    pBtReq,
    PBT_RSP_CMD    pBtRsp
)
{
    u1Byte                h2cParaBuf[6] = {0};
    u1Byte                h2cParaLen = 0;
    u2Byte                paraLen = 0;
    u1Byte                retStatus = BT_STATUS_BT_OP_SUCCESS;
    u1Byte                btOpcode;
    u1Byte                btOpcodeVer = 0;
    PMPT_CONTEXT        pMptCtx = &(Adapter->mppriv.mpt_ctx);
    PBT_EXT_C2H            pExtC2h = (PBT_EXT_C2H)&pMptCtx->c2hBuf[0];
    u1Byte                i;
    u1Byte                btFwVer = 0, bdAddr[6] = {0};
    u2Byte                btRealFwVer = 0;
    pu2Byte            pu2Tmp = NULL;
    /*  */
    /* check upper layer parameters */
    /*  */
    /* 1. check upper layer opcode version */
    if (pBtReq->opCodeVer != 1) {
        RTW_INFO("[MPT], Error!! Upper OP code version not match!!!\n");
        pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
        return paraLen;
    }
    pBtRsp->pParamStart[0] = MP_BT_NOT_READY;
    paraLen = 10;
    /*  */
    /* execute lower layer opcodes */
    /*  */
    /* Get BT FW version */
    /* fill h2c parameters */
    btOpcode = BT_LO_OP_GET_BT_VERSION;
    /* execute h2c and check respond c2h from bt fw is correct or not */
    retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
    /* ckeck bt return status. */
    if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
        pBtRsp->status = ((btOpcode << 8) | retStatus);
        RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
        return paraLen;
    } else {
        pu2Tmp = (pu2Byte)&pExtC2h->buf[0];
        btRealFwVer = *pu2Tmp;
        btFwVer = pExtC2h->buf[1];
        RTW_INFO("[MPT], btRealFwVer=0x%x, btFwVer=0x%x\n", btRealFwVer, btFwVer);
    }
    /* Get BD Address */
    /* fill h2c parameters */
    btOpcode = BT_LO_OP_GET_BD_ADDR_L;
    /* execute h2c and check respond c2h from bt fw is correct or not */
    retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
    /* ckeck bt return status. */
    if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
        pBtRsp->status = ((btOpcode << 8) | retStatus);
        RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
        return paraLen;
    } else {
        bdAddr[5] = pExtC2h->buf[0];
        bdAddr[4] = pExtC2h->buf[1];
        bdAddr[3] = pExtC2h->buf[2];
    }
    /* fill h2c parameters */
    btOpcode = BT_LO_OP_GET_BD_ADDR_H;
    /* execute h2c and check respond c2h from bt fw is correct or not */
    retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
    /* ckeck bt return status. */
    if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
        pBtRsp->status = ((btOpcode << 8) | retStatus);
        RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
        return paraLen;
    } else {
        bdAddr[2] = pExtC2h->buf[0];
        bdAddr[1] = pExtC2h->buf[1];
        bdAddr[0] = pExtC2h->buf[2];
    }
    RTW_INFO("[MPT], Local BDAddr:");
    for (i = 0; i < 6; i++)
        RTW_INFO(" 0x%x ", bdAddr[i]);
    pBtRsp->status = BT_STATUS_SUCCESS;
    pBtRsp->pParamStart[0] = MP_BT_READY;
    pu2Tmp = (pu2Byte)&pBtRsp->pParamStart[1];
    *pu2Tmp = btRealFwVer;
    pBtRsp->pParamStart[3] = btFwVer;
    for (i = 0; i < 6; i++)
        pBtRsp->pParamStart[4 + i] = bdAddr[5 - i];
    return paraLen;
}
void mptbt_close_WiFiRF(PADAPTER Adapter)
{
    phy_set_bb_reg(Adapter, 0x824, 0xF, 0x0);
    phy_set_bb_reg(Adapter, 0x824, 0x700000, 0x0);
    phy_set_rf_reg(Adapter, RF_PATH_A, 0x0, 0xF0000, 0x0);
}
void mptbt_open_WiFiRF(PADAPTER    Adapter)
{
    phy_set_bb_reg(Adapter, 0x824, 0x700000, 0x3);
    phy_set_bb_reg(Adapter, 0x824, 0xF, 0x2);
    phy_set_rf_reg(Adapter, RF_PATH_A, 0x0, 0xF0000, 0x3);
}
u4Byte mptbt_switch_RF(PADAPTER    Adapter, u1Byte    Enter)
{
    u2Byte    tmp_2byte = 0;
    /* Enter test mode */
    if (Enter) {
        /* 1>. close WiFi RF */
        mptbt_close_WiFiRF(Adapter);
        /* 2>. change ant switch to BT */
        tmp_2byte = rtw_read16(Adapter, 0x860);
        tmp_2byte = tmp_2byte | BIT(9);
        tmp_2byte = tmp_2byte & (~BIT(8));
        rtw_write16(Adapter, 0x860, tmp_2byte);
        rtw_write16(Adapter, 0x870, 0x300);
    } else {
        /* 1>. Open WiFi RF */
        mptbt_open_WiFiRF(Adapter);
        /* 2>. change ant switch back */
        tmp_2byte = rtw_read16(Adapter, 0x860);
        tmp_2byte = tmp_2byte | BIT(8);
        tmp_2byte = tmp_2byte & (~BIT(9));
        rtw_write16(Adapter, 0x860, tmp_2byte);
        rtw_write16(Adapter, 0x870, 0x300);
    }
    return 0;
}
u2Byte
mptbt_BtSetMode(
    PADAPTER        Adapter,
    PBT_REQ_CMD    pBtReq,
    PBT_RSP_CMD    pBtRsp
)
{
    u1Byte                h2cParaBuf[6] = {0};
    u1Byte                h2cParaLen = 0;
    u2Byte                paraLen = 0;
    u1Byte                retStatus = BT_STATUS_BT_OP_SUCCESS;
    u1Byte                btOpcode;
    u1Byte                btOpcodeVer = 0;
    u1Byte                btModeToSet = 0;
    /*  */
    /* check upper layer parameters */
    /*  */
    /* 1. check upper layer opcode version */
    if (pBtReq->opCodeVer != 1) {
        RTW_INFO("[MPT], Error!! Upper OP code version not match!!!\n");
        pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
        return paraLen;
    }
    /* 2. check upper layer parameter length */
    if (1 == pBtReq->paraLength) {
        btModeToSet = pBtReq->pParamStart[0];
        RTW_INFO("[MPT], BtTestMode=%d\n", btModeToSet);
    } else {
        RTW_INFO("[MPT], Error!! wrong parameter length=%d (should be 1)\n", pBtReq->paraLength);
        pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
        return paraLen;
    }
    /*  */
    /* execute lower layer opcodes */
    /*  */
    /* 1. fill h2c parameters     */
    /* check bt mode */
    btOpcode = BT_LO_OP_SET_BT_MODE;
    if (btModeToSet >= MP_BT_MODE_MAX) {
        pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
        return paraLen;
    } else {
        mptbt_switch_RF(Adapter, 1);
        h2cParaBuf[0] = btModeToSet;
        h2cParaLen = 1;
        /* 2. execute h2c and check respond c2h from bt fw is correct or not */
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
    }
    /* 3. construct respond status code and data. */
    if (BT_STATUS_BT_OP_SUCCESS == retStatus)
        pBtRsp->status = BT_STATUS_SUCCESS;
    else {
        pBtRsp->status = ((btOpcode << 8) | retStatus);
        RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
    }
    return paraLen;
}
VOID
MPTBT_FwC2hBtMpCtrl(
    PADAPTER    Adapter,
    pu1Byte    tmpBuf,
    u1Byte        length
)
{
    u32 i;
    PMPT_CONTEXT    pMptCtx = &(Adapter->mppriv.mpt_ctx);
    PBT_EXT_C2H pExtC2h = (PBT_EXT_C2H)tmpBuf;
    if (Adapter->bBTFWReady == _FALSE || Adapter->registrypriv.mp_mode == 0) {
        /* RTW_INFO("Ignore C2H BT MP Info since not in MP mode\n"); */
        return;
    }
    if (length > 32 || length < 3) {
        RTW_INFO("\n [MPT], pExtC2h->buf hex: length=%d > 32 || < 3\n", length);
        return;
    }
    /* cancel_timeout for h2c handle */
    _cancel_timer_ex(&pMptCtx->MPh2c_timeout_timer);
    for (i = 0; i < length; i++)
        RTW_INFO("[MPT], %s, buf[%d]=0x%02x ", __FUNCTION__, i, tmpBuf[i]);
    RTW_INFO("[MPT], pExtC2h->extendId=0x%x\n", pExtC2h->extendId);
    switch (pExtC2h->extendId) {
    case EXT_C2H_WIFI_FW_ACTIVE_RSP:
        RTW_INFO("[MPT], EXT_C2H_WIFI_FW_ACTIVE_RSP\n");
#if 0
        RTW_INFO("[MPT], pExtC2h->buf hex:\n");
        for (i = 0; i < (length - 3); i++)
            RTW_INFO(" 0x%x ", pExtC2h->buf[i]);
#endif
        if ((_FALSE == pMptCtx->bMPh2c_timeout)
            && (_FALSE == pMptCtx->MptH2cRspEvent)) {
            pMptCtx->MptH2cRspEvent = _TRUE;
            _rtw_up_sema(&pMptCtx->MPh2c_Sema);
        }
        break;
    case EXT_C2H_TRIG_BY_BT_FW:
        RTW_INFO("[MPT], EXT_C2H_TRIG_BY_BT_FW\n");
        _rtw_memcpy(&pMptCtx->c2hBuf[0], tmpBuf, length);
        RTW_INFO("[MPT], pExtC2h->statusCode=0x%x\n", pExtC2h->statusCode);
        RTW_INFO("[MPT], pExtC2h->retLen=0x%x\n", pExtC2h->retLen);
        RTW_INFO("[MPT], pExtC2h->opCodeVer=0x%x\n", pExtC2h->opCodeVer);
        RTW_INFO("[MPT], pExtC2h->reqNum=0x%x\n", pExtC2h->reqNum);
        for (i = 0; i < (length - 3); i++)
            RTW_INFO("[MPT], pExtC2h->buf[%d]=0x%02x\n", i, pExtC2h->buf[i]);
        if ((_FALSE == pMptCtx->bMPh2c_timeout)
            && (_TRUE == pMptCtx->MptH2cRspEvent)
            && (_FALSE == pMptCtx->MptBtC2hEvent)) {
            pMptCtx->MptBtC2hEvent = _TRUE;
            _rtw_up_sema(&pMptCtx->MPh2c_Sema);
        }
        break;
    default:
        RTW_INFO("[MPT], EXT_C2H Target not found,pExtC2h->extendId =%d ,pExtC2h->reqNum=%d\n", pExtC2h->extendId, pExtC2h->reqNum);
        break;
    }
}
u2Byte
mptbt_BtGetGeneral(
    IN    PADAPTER        Adapter,
    IN    PBT_REQ_CMD    pBtReq,
    IN    PBT_RSP_CMD    pBtRsp
)
{
    PMPT_CONTEXT        pMptCtx = &(Adapter->mppriv.mpt_ctx);
    PBT_EXT_C2H        pExtC2h = (PBT_EXT_C2H)&pMptCtx->c2hBuf[0];
    u1Byte                h2cParaBuf[6] = {0};
    u1Byte                h2cParaLen = 0;
    u2Byte                paraLen = 0;
    u1Byte                retStatus = BT_STATUS_BT_OP_SUCCESS;
    u1Byte                btOpcode, bdAddr[6] = {0};
    u1Byte                btOpcodeVer = 0;
    u1Byte                getType = 0, i;
    u2Byte                getParaLen = 0, validParaLen = 0;
    u1Byte                regType = 0, reportType = 0;
    u4Byte                regAddr = 0, regValue = 0;
    pu4Byte            pu4Tmp;
    pu2Byte            pu2Tmp;
    pu1Byte            pu1Tmp;
    /*  */
    /* check upper layer parameters */
    /*  */
    /* check upper layer opcode version */
    if (pBtReq->opCodeVer != 1) {
        RTW_INFO("[MPT], Error!! Upper OP code version not match!!!\n");
        pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
        return paraLen;
    }
    /* check upper layer parameter length */
    if (pBtReq->paraLength < 1) {
        RTW_INFO("[MPT], Error!! wrong parameter length=%d (should larger than 1)\n", pBtReq->paraLength);
        pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
        return paraLen;
    }
    getParaLen = pBtReq->paraLength - 1;
    getType = pBtReq->pParamStart[0];
    RTW_INFO("[MPT], getType=%d, getParaLen=%d\n", getType, getParaLen);
    /* check parameter first */
    switch (getType) {
    case BT_GGET_REG:
        RTW_INFO("[MPT], [BT_GGET_REG]\n");
        validParaLen = 5;
        if (getParaLen == validParaLen) {
            btOpcode = BT_LO_OP_READ_REG;
            regType = pBtReq->pParamStart[1];
            pu4Tmp = (pu4Byte)&pBtReq->pParamStart[2];
            regAddr = *pu4Tmp;
            RTW_INFO("[MPT], BT_GGET_REG regType=0x%02x, regAddr=0x%08x!!\n",
                 regType, regAddr);
            if (regType >= BT_REG_MAX) {
                pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
                return paraLen;
            } else {
                if (((BT_REG_RF == regType) && (regAddr > 0x7f)) ||
                    ((BT_REG_MODEM == regType) && (regAddr > 0x1ff)) ||
                    ((BT_REG_BLUEWIZE == regType) && (regAddr > 0xfff)) ||
                    ((BT_REG_VENDOR == regType) && (regAddr > 0xfff)) ||
                    ((BT_REG_LE == regType) && (regAddr > 0xfff))) {
                    pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
                    return paraLen;
                }
            }
        }
        break;
    case BT_GGET_STATUS:
        RTW_INFO("[MPT], [BT_GGET_STATUS]\n");
        validParaLen = 0;
        break;
    case BT_GGET_REPORT:
        RTW_INFO("[MPT], [BT_GGET_REPORT]\n");
        validParaLen = 1;
        if (getParaLen == validParaLen) {
            reportType = pBtReq->pParamStart[1];
            RTW_INFO("[MPT], BT_GGET_REPORT reportType=0x%x!!\n", reportType);
            if (reportType >= BT_REPORT_MAX) {
                pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
                return paraLen;
            }
        }
        break;
    default: {
        RTW_INFO("[MPT], Error!! getType=%d, out of range\n", getType);
        pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
        return paraLen;
    }
    break;
    }
    if (getParaLen != validParaLen) {
        RTW_INFO("[MPT], Error!! wrong parameter length=%d for BT_GET_GEN_CMD cmd id=0x%x, paraLen should=0x%x\n",
             getParaLen, getType, validParaLen);
        pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
        return paraLen;
    }
    /*  */
    /* execute lower layer opcodes */
    /*  */
    if (BT_GGET_REG == getType) {
        /* fill h2c parameters */
        /* here we should write reg value first then write the address, adviced by Austin */
        btOpcode = BT_LO_OP_READ_REG;
        h2cParaBuf[0] = regType;
        h2cParaBuf[1] = pBtReq->pParamStart[2];
        h2cParaBuf[2] = pBtReq->pParamStart[3];
        h2cParaLen = 3;
        /* execute h2c and check respond c2h from bt fw is correct or not */
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
        /* construct respond status code and data. */
        if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
            pBtRsp->status = ((btOpcode << 8) | retStatus);
            RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
            return paraLen;
        }
        pu2Tmp = (pu2Byte)&pExtC2h->buf[0];
        regValue = *pu2Tmp;
        RTW_INFO("[MPT], read reg regType=0x%02x, regAddr=0x%08x, regValue=0x%04x\n",
             regType, regAddr, regValue);
        pu4Tmp = (pu4Byte)&pBtRsp->pParamStart[0];
        *pu4Tmp = regValue;
        paraLen = 4;
    } else if (BT_GGET_STATUS == getType) {
        btOpcode = BT_LO_OP_GET_BT_STATUS;
        h2cParaLen = 0;
        /* execute h2c and check respond c2h from bt fw is correct or not */
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
        /* construct respond status code and data. */
        if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
            pBtRsp->status = ((btOpcode << 8) | retStatus);
            RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
            return paraLen;
        }
        pBtRsp->pParamStart[0] = pExtC2h->buf[0];
        pBtRsp->pParamStart[1] = pExtC2h->buf[1];
        RTW_INFO("[MPT], read bt status, testMode=0x%x, testStatus=0x%x\n",
             pBtRsp->pParamStart[0], pBtRsp->pParamStart[1]);
        paraLen = 2;
    } else if (BT_GGET_REPORT == getType) {
        switch (reportType) {
        case BT_REPORT_RX_PACKET_CNT: {
            RTW_INFO("[MPT], [Rx Packet Counts]\n");
            btOpcode = BT_LO_OP_GET_RX_PKT_CNT_L;
            h2cParaLen = 0;
            /* execute h2c and check respond c2h from bt fw is correct or not */
            retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
            /* construct respond status code and data. */
            if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
                pBtRsp->status = ((btOpcode << 8) | retStatus);
                RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
                return paraLen;
            }
            pBtRsp->pParamStart[0] = pExtC2h->buf[0];
            pBtRsp->pParamStart[1] = pExtC2h->buf[1];
            btOpcode = BT_LO_OP_GET_RX_PKT_CNT_H;
            h2cParaLen = 0;
            /* execute h2c and check respond c2h from bt fw is correct or not */
            retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
            /* construct respond status code and data. */
            if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
                pBtRsp->status = ((btOpcode << 8) | retStatus);
                RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
                return paraLen;
            }
            pBtRsp->pParamStart[2] = pExtC2h->buf[0];
            pBtRsp->pParamStart[3] = pExtC2h->buf[1];
            paraLen = 4;
        }
        break;
        case BT_REPORT_RX_ERROR_BITS: {
            RTW_INFO("[MPT], [Rx Error Bits]\n");
            btOpcode = BT_LO_OP_GET_RX_ERROR_BITS_L;
            h2cParaLen = 0;
            /* execute h2c and check respond c2h from bt fw is correct or not */
            retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
            /* construct respond status code and data. */
            if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
                pBtRsp->status = ((btOpcode << 8) | retStatus);
                RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
                return paraLen;
            }
            pBtRsp->pParamStart[0] = pExtC2h->buf[0];
            pBtRsp->pParamStart[1] = pExtC2h->buf[1];
            btOpcode = BT_LO_OP_GET_RX_ERROR_BITS_H;
            h2cParaLen = 0;
            /* execute h2c and check respond c2h from bt fw is correct or not */
            retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
            /* construct respond status code and data. */
            if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
                pBtRsp->status = ((btOpcode << 8) | retStatus);
                RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
                return paraLen;
            }
            pBtRsp->pParamStart[2] = pExtC2h->buf[0];
            pBtRsp->pParamStart[3] = pExtC2h->buf[1];
            paraLen = 4;
        }
        break;
        case BT_REPORT_RSSI: {
            RTW_INFO("[MPT], [RSSI]\n");
            btOpcode = BT_LO_OP_GET_RSSI;
            h2cParaLen = 0;
            /* execute h2c and check respond c2h from bt fw is correct or not */
            retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
            /* construct respond status code and data. */
            if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
                pBtRsp->status = ((btOpcode << 8) | retStatus);
                RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
                return paraLen;
            }
            pBtRsp->pParamStart[0] = pExtC2h->buf[0];
            pBtRsp->pParamStart[1] = pExtC2h->buf[1];
            paraLen = 2;
        }
        break;
        case BT_REPORT_CFO_HDR_QUALITY: {
            RTW_INFO("[MPT], [CFO & Header Quality]\n");
            btOpcode = BT_LO_OP_GET_CFO_HDR_QUALITY_L;
            h2cParaLen = 0;
            /* execute h2c and check respond c2h from bt fw is correct or not */
            retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
            /* construct respond status code and data. */
            if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
                pBtRsp->status = ((btOpcode << 8) | retStatus);
                RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
                return paraLen;
            }
            pBtRsp->pParamStart[0] = pExtC2h->buf[0];
            pBtRsp->pParamStart[1] = pExtC2h->buf[1];
            btOpcode = BT_LO_OP_GET_CFO_HDR_QUALITY_H;
            h2cParaLen = 0;
            /* execute h2c and check respond c2h from bt fw is correct or not */
            retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
            /* construct respond status code and data. */
            if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
                pBtRsp->status = ((btOpcode << 8) | retStatus);
                RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
                return paraLen;
            }
            pBtRsp->pParamStart[2] = pExtC2h->buf[0];
            pBtRsp->pParamStart[3] = pExtC2h->buf[1];
            paraLen = 4;
        }
        break;
        case BT_REPORT_CONNECT_TARGET_BD_ADDR: {
            RTW_INFO("[MPT], [Connected Target BD ADDR]\n");
            btOpcode = BT_LO_OP_GET_TARGET_BD_ADDR_L;
            h2cParaLen = 0;
            /* execute h2c and check respond c2h from bt fw is correct or not */
            retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
            /* construct respond status code and data. */
            if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
                pBtRsp->status = ((btOpcode << 8) | retStatus);
                RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
                return paraLen;
            }
            bdAddr[5] = pExtC2h->buf[0];
            bdAddr[4] = pExtC2h->buf[1];
            bdAddr[3] = pExtC2h->buf[2];
            btOpcode = BT_LO_OP_GET_TARGET_BD_ADDR_H;
            h2cParaLen = 0;
            /* execute h2c and check respond c2h from bt fw is correct or not */
            retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
            /* construct respond status code and data. */
            if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
                pBtRsp->status = ((btOpcode << 8) | retStatus);
                RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
                return paraLen;
            }
            bdAddr[2] = pExtC2h->buf[0];
            bdAddr[1] = pExtC2h->buf[1];
            bdAddr[0] = pExtC2h->buf[2];
            RTW_INFO("[MPT], Connected Target BDAddr:%s", bdAddr);
            for (i = 0; i < 6; i++)
                pBtRsp->pParamStart[i] = bdAddr[5 - i];
            paraLen = 6;
        }
        break;
        default:
            pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
            return paraLen;
            break;
        }
    }
    pBtRsp->status = BT_STATUS_SUCCESS;
    return paraLen;
}
u2Byte
mptbt_BtSetGeneral(
    IN    PADAPTER        Adapter,
    IN    PBT_REQ_CMD    pBtReq,
    IN    PBT_RSP_CMD    pBtRsp
)
{
    u1Byte                h2cParaBuf[6] = {0};
    u1Byte                h2cParaLen = 0;
    u2Byte                paraLen = 0;
    u1Byte                retStatus = BT_STATUS_BT_OP_SUCCESS;
    u1Byte                btOpcode;
    u1Byte                btOpcodeVer = 0;
    u1Byte                setType = 0;
    u2Byte                setParaLen = 0, validParaLen = 0;
    u1Byte                regType = 0, bdAddr[6] = {0}, calVal = 0;
    u4Byte                regAddr = 0, regValue = 0;
    pu4Byte            pu4Tmp;
    pu2Byte            pu2Tmp;
    pu1Byte            pu1Tmp;
    /*  */
    /* check upper layer parameters */
    /*  */
    /* check upper layer opcode version */
    if (pBtReq->opCodeVer != 1) {
        RTW_INFO("[MPT], Error!! Upper OP code version not match!!!\n");
        pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
        return paraLen;
    }
    /* check upper layer parameter length */
    if (pBtReq->paraLength < 1) {
        RTW_INFO("[MPT], Error!! wrong parameter length=%d (should larger than 1)\n", pBtReq->paraLength);
        pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
        return paraLen;
    }
    setParaLen = pBtReq->paraLength - 1;
    setType = pBtReq->pParamStart[0];
    RTW_INFO("[MPT], setType=%d, setParaLen=%d\n", setType, setParaLen);
    /* check parameter first */
    switch (setType) {
    case BT_GSET_REG:
        RTW_INFO("[MPT], [BT_GSET_REG]\n");
        validParaLen = 9;
        if (setParaLen == validParaLen) {
            btOpcode = BT_LO_OP_WRITE_REG_VALUE;
            regType = pBtReq->pParamStart[1];
            pu4Tmp = (pu4Byte)&pBtReq->pParamStart[2];
            regAddr = *pu4Tmp;
            pu4Tmp = (pu4Byte)&pBtReq->pParamStart[6];
            regValue = *pu4Tmp;
            RTW_INFO("[MPT], BT_GSET_REG regType=0x%x, regAddr=0x%x, regValue=0x%x!!\n",
                 regType, regAddr, regValue);
            if (regType >= BT_REG_MAX) {
                pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
                return paraLen;
            } else {
                if (((BT_REG_RF == regType) && (regAddr > 0x7f)) ||
                    ((BT_REG_MODEM == regType) && (regAddr > 0x1ff)) ||
                    ((BT_REG_BLUEWIZE == regType) && (regAddr > 0xfff)) ||
                    ((BT_REG_VENDOR == regType) && (regAddr > 0xfff)) ||
                    ((BT_REG_LE == regType) && (regAddr > 0xfff))) {
                    pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
                    return paraLen;
                }
            }
        }
        break;
    case BT_GSET_RESET:
        RTW_INFO("[MPT], [BT_GSET_RESET]\n");
        validParaLen = 0;
        break;
    case BT_GSET_TARGET_BD_ADDR:
        RTW_INFO("[MPT], [BT_GSET_TARGET_BD_ADDR]\n");
        validParaLen = 6;
        if (setParaLen == validParaLen) {
            btOpcode = BT_LO_OP_SET_TARGET_BD_ADDR_H;
            if ((pBtReq->pParamStart[1] == 0) &&
                (pBtReq->pParamStart[2] == 0) &&
                (pBtReq->pParamStart[3] == 0) &&
                (pBtReq->pParamStart[4] == 0) &&
                (pBtReq->pParamStart[5] == 0) &&
                (pBtReq->pParamStart[6] == 0)) {
                RTW_INFO("[MPT], Error!! targetBDAddr=all zero\n");
                pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
                return paraLen;
            }
            if ((pBtReq->pParamStart[1] == 0xff) &&
                (pBtReq->pParamStart[2] == 0xff) &&
                (pBtReq->pParamStart[3] == 0xff) &&
                (pBtReq->pParamStart[4] == 0xff) &&
                (pBtReq->pParamStart[5] == 0xff) &&
                (pBtReq->pParamStart[6] == 0xff)) {
                RTW_INFO("[MPT], Error!! targetBDAddr=all 0xf\n");
                pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
                return paraLen;
            }
            bdAddr[0] = pBtReq->pParamStart[6];
            bdAddr[1] = pBtReq->pParamStart[5];
            bdAddr[2] = pBtReq->pParamStart[4];
            bdAddr[3] = pBtReq->pParamStart[3];
            bdAddr[4] = pBtReq->pParamStart[2];
            bdAddr[5] = pBtReq->pParamStart[1];
            RTW_INFO("[MPT], target BDAddr:%x,%x,%x,%x,%x,%x\n",
                bdAddr[0], bdAddr[1], bdAddr[2], bdAddr[3], bdAddr[4], bdAddr[5]);
        }
        break;
    case BT_GSET_TX_PWR_FINETUNE:
        RTW_INFO("[MPT], [BT_GSET_TX_PWR_FINETUNE]\n");
        validParaLen = 1;
        if (setParaLen == validParaLen) {
            btOpcode = BT_LO_OP_SET_TX_POWER_CALIBRATION;
            calVal = pBtReq->pParamStart[1];
            if ((calVal < 1) || (calVal > 9)) {
                pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
                return paraLen;
            }
            RTW_INFO("[MPT], calVal=%d\n", calVal);
        }
        break;
    case BT_SET_TRACKING_INTERVAL:
        RTW_INFO("[MPT], [BT_SET_TRACKING_INTERVAL] setParaLen =%d\n", setParaLen);
        validParaLen = 1;
        if (setParaLen == validParaLen)
            calVal = pBtReq->pParamStart[1];
        break;
    case BT_SET_THERMAL_METER:
        RTW_INFO("[MPT], [BT_SET_THERMAL_METER] setParaLen =%d\n", setParaLen);
        validParaLen = 1;
        if (setParaLen == validParaLen)
            calVal = pBtReq->pParamStart[1];
        break;
    case BT_ENABLE_CFO_TRACKING:
        RTW_INFO("[MPT], [BT_ENABLE_CFO_TRACKING] setParaLen =%d\n", setParaLen);
        validParaLen = 1;
        if (setParaLen == validParaLen)
            calVal = pBtReq->pParamStart[1];
        break;
    case BT_GSET_UPDATE_BT_PATCH:
        break;
    default: {
        RTW_INFO("[MPT], Error!! setType=%d, out of range\n", setType);
        pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
        return paraLen;
    }
    break;
    }
    if (setParaLen != validParaLen) {
        RTW_INFO("[MPT], Error!! wrong parameter length=%d for BT_SET_GEN_CMD cmd id=0x%x, paraLen should=0x%x\n",
             setParaLen, setType, validParaLen);
        pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
        return paraLen;
    }
    /*  */
    /* execute lower layer opcodes */
    /*  */
    if (BT_GSET_REG == setType) {
        /* fill h2c parameters */
        /* here we should write reg value first then write the address, adviced by Austin */
        btOpcode = BT_LO_OP_WRITE_REG_VALUE;
        h2cParaBuf[0] = pBtReq->pParamStart[6];
        h2cParaBuf[1] = pBtReq->pParamStart[7];
        h2cParaBuf[2] = pBtReq->pParamStart[8];
        h2cParaLen = 3;
        /* execute h2c and check respond c2h from bt fw is correct or not */
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
        /* construct respond status code and data. */
        if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
            pBtRsp->status = ((btOpcode << 8) | retStatus);
            RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
            return paraLen;
        }
        /* write reg address */
        btOpcode = BT_LO_OP_WRITE_REG_ADDR;
        h2cParaBuf[0] = regType;
        h2cParaBuf[1] = pBtReq->pParamStart[2];
        h2cParaBuf[2] = pBtReq->pParamStart[3];
        h2cParaLen = 3;
        /* execute h2c and check respond c2h from bt fw is correct or not */
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
        /* construct respond status code and data. */
        if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
            pBtRsp->status = ((btOpcode << 8) | retStatus);
            RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
            return paraLen;
        }
    } else if (BT_GSET_RESET == setType) {
        btOpcode = BT_LO_OP_RESET;
        h2cParaLen = 0;
        /* execute h2c and check respond c2h from bt fw is correct or not */
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
        /* construct respond status code and data. */
        if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
            pBtRsp->status = ((btOpcode << 8) | retStatus);
            RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
            return paraLen;
        }
    } else if (BT_GSET_TARGET_BD_ADDR == setType) {
        /* fill h2c parameters */
        btOpcode = BT_LO_OP_SET_TARGET_BD_ADDR_L;
        h2cParaBuf[0] = pBtReq->pParamStart[1];
        h2cParaBuf[1] = pBtReq->pParamStart[2];
        h2cParaBuf[2] = pBtReq->pParamStart[3];
        h2cParaLen = 3;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
        /* ckeck bt return status. */
        if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
            pBtRsp->status = ((btOpcode << 8) | retStatus);
            RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
            return paraLen;
        }
        btOpcode = BT_LO_OP_SET_TARGET_BD_ADDR_H;
        h2cParaBuf[0] = pBtReq->pParamStart[4];
        h2cParaBuf[1] = pBtReq->pParamStart[5];
        h2cParaBuf[2] = pBtReq->pParamStart[6];
        h2cParaLen = 3;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
        /* ckeck bt return status. */
        if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
            pBtRsp->status = ((btOpcode << 8) | retStatus);
            RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
            return paraLen;
        }
    } else if (BT_GSET_TX_PWR_FINETUNE == setType) {
        /* fill h2c parameters */
        btOpcode = BT_LO_OP_SET_TX_POWER_CALIBRATION;
        h2cParaBuf[0] = calVal;
        h2cParaLen = 1;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
        /* ckeck bt return status. */
        if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
            pBtRsp->status = ((btOpcode << 8) | retStatus);
            RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
            return paraLen;
        }
    } else if (BT_SET_TRACKING_INTERVAL == setType) {
        /*    BT_LO_OP_SET_TRACKING_INTERVAL                                = 0x22, */
        /*    BT_LO_OP_SET_THERMAL_METER                                    = 0x23, */
        /*    BT_LO_OP_ENABLE_CFO_TRACKING                                    = 0x24, */
        btOpcode = BT_LO_OP_SET_TRACKING_INTERVAL;
        h2cParaBuf[0] = calVal;
        h2cParaLen = 1;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
        /* ckeck bt return status. */
        if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
            pBtRsp->status = ((btOpcode << 8) | retStatus);
            RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
            return paraLen;
        }
    } else if (BT_SET_THERMAL_METER == setType) {
        btOpcode = BT_LO_OP_SET_THERMAL_METER;
        h2cParaBuf[0] = calVal;
        h2cParaLen = 1;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
        /* ckeck bt return status. */
        if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
            pBtRsp->status = ((btOpcode << 8) | retStatus);
            RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
            return paraLen;
        }
    } else if (BT_ENABLE_CFO_TRACKING == setType) {
        btOpcode = BT_LO_OP_ENABLE_CFO_TRACKING;
        h2cParaBuf[0] = calVal;
        h2cParaLen = 1;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
        /* ckeck bt return status. */
        if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
            pBtRsp->status = ((btOpcode << 8) | retStatus);
            RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
            return paraLen;
        }
    }
    pBtRsp->status = BT_STATUS_SUCCESS;
    return paraLen;
}
u2Byte
mptbt_BtSetTxRxPars(
    IN    PADAPTER        Adapter,
    IN    PBT_REQ_CMD    pBtReq,
    IN    PBT_RSP_CMD    pBtRsp
)
{
    u1Byte                h2cParaBuf[6] = {0};
    u1Byte                h2cParaLen = 0;
    u2Byte                paraLen = 0;
    u1Byte                retStatus = BT_STATUS_BT_OP_SUCCESS;
    u1Byte                btOpcode;
    u1Byte                btOpcodeVer = 0;
    PBT_TXRX_PARAMETERS pTxRxPars = (PBT_TXRX_PARAMETERS)&pBtReq->pParamStart[0];
    u2Byte                lenTxRx = sizeof(BT_TXRX_PARAMETERS);
    u1Byte                i;
    u1Byte                bdAddr[6] = {0};
    /*  */
    /* check upper layer parameters */
    /*  */
    /* 1. check upper layer opcode version */
    if (pBtReq->opCodeVer != 1) {
        RTW_INFO("[MPT], Error!! Upper OP code version not match!!!\n");
        pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
        return paraLen;
    }
    /* 2. check upper layer parameter length */
    if (pBtReq->paraLength == sizeof(BT_TXRX_PARAMETERS)) {
        RTW_INFO("[MPT], pTxRxPars->txrxChannel=0x%x\n", pTxRxPars->txrxChannel);
        RTW_INFO("[MPT], pTxRxPars->txrxTxPktCnt=0x%8x\n", pTxRxPars->txrxTxPktCnt);
        RTW_INFO("[MPT], pTxRxPars->txrxTxPktInterval=0x%x\n", pTxRxPars->txrxTxPktInterval);
        RTW_INFO("[MPT], pTxRxPars->txrxPayloadType=0x%x\n", pTxRxPars->txrxPayloadType);
        RTW_INFO("[MPT], pTxRxPars->txrxPktType=0x%x\n", pTxRxPars->txrxPktType);
        RTW_INFO("[MPT], pTxRxPars->txrxPayloadLen=0x%x\n", pTxRxPars->txrxPayloadLen);
        RTW_INFO("[MPT], pTxRxPars->txrxPktHeader=0x%x\n", pTxRxPars->txrxPktHeader);
        RTW_INFO("[MPT], pTxRxPars->txrxWhitenCoeff=0x%x\n", pTxRxPars->txrxWhitenCoeff);
        bdAddr[0] = pTxRxPars->txrxBdaddr[5];
        bdAddr[1] = pTxRxPars->txrxBdaddr[4];
        bdAddr[2] = pTxRxPars->txrxBdaddr[3];
        bdAddr[3] = pTxRxPars->txrxBdaddr[2];
        bdAddr[4] = pTxRxPars->txrxBdaddr[1];
        bdAddr[5] = pTxRxPars->txrxBdaddr[0];
        RTW_INFO("[MPT], pTxRxPars->txrxBdaddr: %s", &bdAddr[0]);
        RTW_INFO("[MPT], pTxRxPars->txrxTxGainIndex=0x%x\n", pTxRxPars->txrxTxGainIndex);
    } else {
        RTW_INFO("[MPT], Error!! pBtReq->paraLength=%d, correct Len=%d\n", pBtReq->paraLength, lenTxRx);
        pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
        return paraLen;
    }
    /*  */
    /* execute lower layer opcodes */
    /*  */
    /* fill h2c parameters */
    btOpcode = BT_LO_OP_SET_PKT_HEADER;
    if (pTxRxPars->txrxPktHeader > 0x3ffff) {
        RTW_INFO("[MPT], Error!! pTxRxPars->txrxPktHeader=0x%x is out of range, (should be between 0x0~0x3ffff)\n", pTxRxPars->txrxPktHeader);
        pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
        return paraLen;
    } else {
        h2cParaBuf[0] = (u1Byte)(pTxRxPars->txrxPktHeader & 0xff);
        h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxPktHeader & 0xff00) >> 8);
        h2cParaBuf[2] = (u1Byte)((pTxRxPars->txrxPktHeader & 0xff0000) >> 16);
        h2cParaLen = 3;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
    }
    /* ckeck bt return status. */
    if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
        pBtRsp->status = ((btOpcode << 8) | retStatus);
        RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
        return paraLen;
    }
    /* fill h2c parameters */
    btOpcode = BT_LO_OP_SET_PKT_TYPE_LEN;
    {
        u2Byte    payloadLenLimit = 0;
        switch (pTxRxPars->txrxPktType) {
        case MP_BT_PKT_DH1:
            payloadLenLimit = 27 * 8;
            break;
        case MP_BT_PKT_DH3:
            payloadLenLimit = 183 * 8;
            break;
        case MP_BT_PKT_DH5:
            payloadLenLimit = 339 * 8;
            break;
        case MP_BT_PKT_2DH1:
            payloadLenLimit = 54 * 8;
            break;
        case MP_BT_PKT_2DH3:
            payloadLenLimit = 367 * 8;
            break;
        case MP_BT_PKT_2DH5:
            payloadLenLimit = 679 * 8;
            break;
        case MP_BT_PKT_3DH1:
            payloadLenLimit = 83 * 8;
            break;
        case MP_BT_PKT_3DH3:
            payloadLenLimit = 552 * 8;
            break;
        case MP_BT_PKT_3DH5:
            payloadLenLimit = 1021 * 8;
            break;
        case MP_BT_PKT_LE:
            payloadLenLimit = 39 * 8;
            break;
        default: {
            RTW_INFO("[MPT], Error!! Unknown pTxRxPars->txrxPktType=0x%x\n", pTxRxPars->txrxPktType);
            pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
            return paraLen;
        }
        break;
        }
        if (pTxRxPars->txrxPayloadLen > payloadLenLimit) {
            RTW_INFO("[MPT], Error!! pTxRxPars->txrxPayloadLen=0x%x, (should smaller than %d)\n",
                 pTxRxPars->txrxPayloadLen, payloadLenLimit);
            pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
            return paraLen;
        }
        h2cParaBuf[0] = pTxRxPars->txrxPktType;
        h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxPayloadLen & 0xff));
        h2cParaBuf[2] = (u1Byte)((pTxRxPars->txrxPayloadLen & 0xff00) >> 8);
        h2cParaLen = 3;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
    }
    /* ckeck bt return status. */
    if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
        pBtRsp->status = ((btOpcode << 8) | retStatus);
        RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
        return paraLen;
    }
    /* fill h2c parameters */
    btOpcode = BT_LO_OP_SET_PKT_CNT_L_PL_TYPE;
    if (pTxRxPars->txrxPayloadType > MP_BT_PAYLOAD_MAX) {
        RTW_INFO("[MPT], Error!! pTxRxPars->txrxPayloadType=0x%x, (should be between 0~4)\n", pTxRxPars->txrxPayloadType);
        pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
        return paraLen;
    } else {
        h2cParaBuf[0] = (u1Byte)((pTxRxPars->txrxTxPktCnt & 0xff));
        h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxTxPktCnt & 0xff00) >> 8);
        h2cParaBuf[2] = pTxRxPars->txrxPayloadType;
        h2cParaLen = 3;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
    }
    /* ckeck bt return status. */
    if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
        pBtRsp->status = ((btOpcode << 8) | retStatus);
        RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
        return paraLen;
    }
    /* fill h2c parameters */
    btOpcode = BT_LO_OP_SET_PKT_CNT_H_PKT_INTV;
    if (pTxRxPars->txrxTxPktInterval > 15) {
        RTW_INFO("[MPT], Error!! pTxRxPars->txrxTxPktInterval=0x%x, (should be between 0~15)\n", pTxRxPars->txrxTxPktInterval);
        pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
        return paraLen;
    } else {
        h2cParaBuf[0] = (u1Byte)((pTxRxPars->txrxTxPktCnt & 0xff0000) >> 16);
        h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxTxPktCnt & 0xff000000) >> 24);
        h2cParaBuf[2] = pTxRxPars->txrxTxPktInterval;
        h2cParaLen = 3;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
    }
    /* ckeck bt return status. */
    if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
        pBtRsp->status = ((btOpcode << 8) | retStatus);
        RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
        return paraLen;
    }
    /* fill h2c parameters */
    btOpcode = BT_LO_OP_SET_WHITENCOEFF;
    {
        h2cParaBuf[0] = pTxRxPars->txrxWhitenCoeff;
        h2cParaLen = 1;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
    }
    /* ckeck bt return status. */
    if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
        pBtRsp->status = ((btOpcode << 8) | retStatus);
        RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
        return paraLen;
    }
    /* fill h2c parameters */
    btOpcode = BT_LO_OP_SET_CHNL_TX_GAIN;
    if ((pTxRxPars->txrxChannel > 78) ||
        (pTxRxPars->txrxTxGainIndex > 7)) {
        RTW_INFO("[MPT], Error!! pTxRxPars->txrxChannel=0x%x, (should be between 0~78)\n", pTxRxPars->txrxChannel);
        RTW_INFO("[MPT], Error!! pTxRxPars->txrxTxGainIndex=0x%x, (should be between 0~7)\n", pTxRxPars->txrxTxGainIndex);
        pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
        return paraLen;
    } else {
        h2cParaBuf[0] = pTxRxPars->txrxChannel;
        h2cParaBuf[1] = pTxRxPars->txrxTxGainIndex;
        h2cParaLen = 2;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
    }
    /* ckeck bt return status. */
    if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
        pBtRsp->status = ((btOpcode << 8) | retStatus);
        RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
        return paraLen;
    }
    /* fill h2c parameters */
    btOpcode = BT_LO_OP_SET_BD_ADDR_L;
    if ((pTxRxPars->txrxBdaddr[0] == 0) &&
        (pTxRxPars->txrxBdaddr[1] == 0) &&
        (pTxRxPars->txrxBdaddr[2] == 0) &&
        (pTxRxPars->txrxBdaddr[3] == 0) &&
        (pTxRxPars->txrxBdaddr[4] == 0) &&
        (pTxRxPars->txrxBdaddr[5] == 0)) {
        RTW_INFO("[MPT], Error!! pTxRxPars->txrxBdaddr=all zero\n");
        pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
        return paraLen;
    }
    if ((pTxRxPars->txrxBdaddr[0] == 0xff) &&
        (pTxRxPars->txrxBdaddr[1] == 0xff) &&
        (pTxRxPars->txrxBdaddr[2] == 0xff) &&
        (pTxRxPars->txrxBdaddr[3] == 0xff) &&
        (pTxRxPars->txrxBdaddr[4] == 0xff) &&
        (pTxRxPars->txrxBdaddr[5] == 0xff)) {
        RTW_INFO("[MPT], Error!! pTxRxPars->txrxBdaddr=all 0xf\n");
        pBtRsp->status = (btOpcode << 8) | BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
        return paraLen;
    }
    {
        h2cParaBuf[0] = pTxRxPars->txrxBdaddr[0];
        h2cParaBuf[1] = pTxRxPars->txrxBdaddr[1];
        h2cParaBuf[2] = pTxRxPars->txrxBdaddr[2];
        h2cParaLen = 3;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
    }
    /* ckeck bt return status. */
    if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
        pBtRsp->status = ((btOpcode << 8) | retStatus);
        RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
        return paraLen;
    }
    btOpcode = BT_LO_OP_SET_BD_ADDR_H;
    {
        h2cParaBuf[0] = pTxRxPars->txrxBdaddr[3];
        h2cParaBuf[1] = pTxRxPars->txrxBdaddr[4];
        h2cParaBuf[2] = pTxRxPars->txrxBdaddr[5];
        h2cParaLen = 3;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
    }
    /* ckeck bt return status. */
    if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
        pBtRsp->status = ((btOpcode << 8) | retStatus);
        RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
        return paraLen;
    }
    pBtRsp->status = BT_STATUS_SUCCESS;
    return paraLen;
}
u2Byte
mptbt_BtTestCtrl(
    IN    PADAPTER        Adapter,
    IN    PBT_REQ_CMD    pBtReq,
    IN    PBT_RSP_CMD    pBtRsp
)
{
    u1Byte                h2cParaBuf[6] = {0};
    u1Byte                h2cParaLen = 0;
    u2Byte                paraLen = 0;
    u1Byte                retStatus = BT_STATUS_BT_OP_SUCCESS;
    u1Byte                btOpcode;
    u1Byte                btOpcodeVer = 0;
    u1Byte                testCtrl = 0;
    /*  */
    /* check upper layer parameters */
    /*  */
    /* 1. check upper layer opcode version */
    if (pBtReq->opCodeVer != 1) {
        RTW_INFO("[MPT], Error!! Upper OP code version not match!!!\n");
        pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
        return paraLen;
    }
    /* 2. check upper layer parameter length */
    if (1 == pBtReq->paraLength) {
        testCtrl = pBtReq->pParamStart[0];
        RTW_INFO("[MPT], testCtrl=%d\n", testCtrl);
    } else {
        RTW_INFO("[MPT], Error!! wrong parameter length=%d (should be 1)\n", pBtReq->paraLength);
        pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
        return paraLen;
    }
    /*  */
    /* execute lower layer opcodes */
    /*  */
    /* 1. fill h2c parameters     */
    /* check bt mode */
    btOpcode = BT_LO_OP_TEST_CTRL;
    if (testCtrl >= MP_BT_TEST_MAX) {
        RTW_INFO("[MPT], Error!! testCtrl=0x%x, (should be between smaller or equal to 0x%x)\n",
             testCtrl, MP_BT_TEST_MAX - 1);
        pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
        return paraLen;
    } else {
        h2cParaBuf[0] = testCtrl;
        h2cParaLen = 1;
        retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
    }
    /* 3. construct respond status code and data. */
    if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
        pBtRsp->status = ((btOpcode << 8) | retStatus);
        RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
        return paraLen;
    }
    pBtRsp->status = BT_STATUS_SUCCESS;
    return paraLen;
}
u2Byte
mptbt_TestBT(
    IN    PADAPTER        Adapter,
    IN    PBT_REQ_CMD    pBtReq,
    IN    PBT_RSP_CMD    pBtRsp
)
{
    u1Byte                h2cParaBuf[6] = {0};
    u1Byte                h2cParaLen = 0;
    u2Byte                paraLen = 0;
    u1Byte                retStatus = BT_STATUS_BT_OP_SUCCESS;
    u1Byte                btOpcode;
    u1Byte                btOpcodeVer = 0;
    u1Byte                testCtrl = 0;
    /* 1. fill h2c parameters     */
    btOpcode =  0x11;
    h2cParaBuf[0] = 0x11;
    h2cParaBuf[1] = 0x0;
    h2cParaBuf[2] = 0x0;
    h2cParaBuf[3] = 0x0;
    h2cParaBuf[4] = 0x0;
    h2cParaLen = 1;
    /*    retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); */
    retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, h2cParaBuf, h2cParaLen);
    /* 3. construct respond status code and data. */
    if (BT_STATUS_BT_OP_SUCCESS != retStatus) {
        pBtRsp->status = ((btOpcode << 8) | retStatus);
        RTW_INFO("[MPT], Error!! status code=0x%x\n", pBtRsp->status);
        return paraLen;
    }
    pBtRsp->status = BT_STATUS_SUCCESS;
    return paraLen;
}
VOID
mptbt_BtControlProcess(
    PADAPTER    Adapter,
    PVOID        pInBuf
)
{
    u1Byte            H2C_Parameter[6] = {0};
    PBT_H2C        pH2c = (PBT_H2C)&H2C_Parameter[0];
    PMPT_CONTEXT    pMptCtx = &(Adapter->mppriv.mpt_ctx);
    PBT_REQ_CMD    pBtReq = (PBT_REQ_CMD)pInBuf;
    PBT_RSP_CMD    pBtRsp;
    u1Byte            i;
    RTW_INFO("[MPT], mptbt_BtControlProcess()=========>\n");
    RTW_INFO("[MPT], input opCodeVer=%d\n", pBtReq->opCodeVer);
    RTW_INFO("[MPT], input OpCode=%d\n", pBtReq->OpCode);
    RTW_INFO("[MPT], paraLength=%d\n", pBtReq->paraLength);
    if (pBtReq->paraLength) {
        /* RTW_INFO("[MPT], parameters(hex):0x%x %d\n",&pBtReq->pParamStart[0], pBtReq->paraLength); */
    }
    _rtw_memset((void *)pMptCtx->mptOutBuf, 0, 100);
    pMptCtx->mptOutLen = 4; /* length of (BT_RSP_CMD.status+BT_RSP_CMD.paraLength) */
    pBtRsp = (PBT_RSP_CMD)pMptCtx->mptOutBuf;
    pBtRsp->status = BT_STATUS_SUCCESS;
    pBtRsp->paraLength = 0x0;
    /* The following we should maintain the User OP codes sent by upper layer */
    switch (pBtReq->OpCode) {
    case BT_UP_OP_BT_READY:
        RTW_INFO("[MPT], OPcode : [BT_READY]\n");
        pBtRsp->paraLength = mptbt_BtReady(Adapter, pBtReq, pBtRsp);
        break;
    case BT_UP_OP_BT_SET_MODE:
        RTW_INFO("[MPT], OPcode : [BT_SET_MODE]\n");
        pBtRsp->paraLength = mptbt_BtSetMode(Adapter, pBtReq, pBtRsp);
        break;
    case BT_UP_OP_BT_SET_TX_RX_PARAMETER:
        RTW_INFO("[MPT], OPcode : [BT_SET_TXRX_PARAMETER]\n");
        pBtRsp->paraLength = mptbt_BtSetTxRxPars(Adapter, pBtReq, pBtRsp);
        break;
    case BT_UP_OP_BT_SET_GENERAL:
        RTW_INFO("[MPT], OPcode : [BT_SET_GENERAL]\n");
        pBtRsp->paraLength = mptbt_BtSetGeneral(Adapter, pBtReq, pBtRsp);
        break;
    case BT_UP_OP_BT_GET_GENERAL:
        RTW_INFO("[MPT], OPcode : [BT_GET_GENERAL]\n");
        pBtRsp->paraLength = mptbt_BtGetGeneral(Adapter, pBtReq, pBtRsp);
        break;
    case BT_UP_OP_BT_TEST_CTRL:
        RTW_INFO("[MPT], OPcode : [BT_TEST_CTRL]\n");
        pBtRsp->paraLength = mptbt_BtTestCtrl(Adapter, pBtReq, pBtRsp);
        break;
    case BT_UP_OP_TEST_BT:
        RTW_INFO("[MPT], OPcode : [TEST_BT]\n");
        pBtRsp->paraLength = mptbt_TestBT(Adapter, pBtReq, pBtRsp);
        break;
    default:
        RTW_INFO("[MPT], Error!! OPcode : UNDEFINED!!!!\n");
        pBtRsp->status = BT_STATUS_UNKNOWN_OPCODE_U;
        pBtRsp->paraLength = 0x0;
        break;
    }
    pMptCtx->mptOutLen += pBtRsp->paraLength;
    RTW_INFO("[MPT], pMptCtx->mptOutLen=%d, pBtRsp->paraLength=%d\n", pMptCtx->mptOutLen, pBtRsp->paraLength);
    RTW_INFO("[MPT], mptbt_BtControlProcess()<=========\n");
}
#endif
linux-bsp/drivers/rtl8188eus/core/rtw_btcoex.c
New file
@@ -0,0 +1,1717 @@
/******************************************************************************
 *
 * Copyright(c) 2013 Realtek Corporation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 *
 ******************************************************************************/
#ifdef CONFIG_BT_COEXIST
#include <drv_types.h>
#include <hal_btcoex.h>
#include <hal_data.h>
void rtw_btcoex_Initialize(PADAPTER padapter)
{
    hal_btcoex_Initialize(padapter);
}
void rtw_btcoex_PowerOnSetting(PADAPTER padapter)
{
    hal_btcoex_PowerOnSetting(padapter);
}
void rtw_btcoex_PreLoadFirmware(PADAPTER padapter)
{
    hal_btcoex_PreLoadFirmware(padapter);
}
void rtw_btcoex_HAL_Initialize(PADAPTER padapter, u8 bWifiOnly)
{
    hal_btcoex_InitHwConfig(padapter, bWifiOnly);
}
void rtw_btcoex_IpsNotify(PADAPTER padapter, u8 type)
{
    PHAL_DATA_TYPE    pHalData;
    pHalData = GET_HAL_DATA(padapter);
    if (_FALSE == pHalData->EEPROMBluetoothCoexist)
        return;
    hal_btcoex_IpsNotify(padapter, type);
}
void rtw_btcoex_LpsNotify(PADAPTER padapter, u8 type)
{
    PHAL_DATA_TYPE    pHalData;
    pHalData = GET_HAL_DATA(padapter);
    if (_FALSE == pHalData->EEPROMBluetoothCoexist)
        return;
    hal_btcoex_LpsNotify(padapter, type);
}
void rtw_btcoex_ScanNotify(PADAPTER padapter, u8 type)
{
    PHAL_DATA_TYPE    pHalData;
#ifdef CONFIG_BT_COEXIST_SOCKET_TRX
    struct bt_coex_info *pcoex_info = &padapter->coex_info;
    PBT_MGNT    pBtMgnt = &pcoex_info->BtMgnt;
#endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
    pHalData = GET_HAL_DATA(padapter);
    if (_FALSE == pHalData->EEPROMBluetoothCoexist)
        return;
    if (_FALSE == type) {
        #ifdef CONFIG_CONCURRENT_MODE
        if (rtw_mi_buddy_check_fwstate(padapter, WIFI_SITE_MONITOR))
            return;
        #endif
        if (DEV_MGMT_TX_NUM(adapter_to_dvobj(padapter))
            || DEV_ROCH_NUM(adapter_to_dvobj(padapter)))
            return;
    }
#ifdef CONFIG_BT_COEXIST_SOCKET_TRX
    if (pBtMgnt->ExtConfig.bEnableWifiScanNotify)
        rtw_btcoex_SendScanNotify(padapter, type);
#endif /* CONFIG_BT_COEXIST_SOCKET_TRX     */
    hal_btcoex_ScanNotify(padapter, type);
}
void rtw_btcoex_ConnectNotify(PADAPTER padapter, u8 action)
{
    PHAL_DATA_TYPE    pHalData;
    pHalData = GET_HAL_DATA(padapter);
    if (_FALSE == pHalData->EEPROMBluetoothCoexist)
        return;
#ifdef DBG_CONFIG_ERROR_RESET
    if (_TRUE == rtw_hal_sreset_inprogress(padapter)) {
        RTW_INFO(FUNC_ADPT_FMT ": [BTCoex] under reset, skip notify!\n",
             FUNC_ADPT_ARG(padapter));
        return;
    }
#endif /* DBG_CONFIG_ERROR_RESET */
#ifdef CONFIG_CONCURRENT_MODE
    if (_FALSE == action) {
        if (rtw_mi_buddy_check_fwstate(padapter, WIFI_UNDER_LINKING))
            return;
    }
#endif
    hal_btcoex_ConnectNotify(padapter, action);
}
void rtw_btcoex_MediaStatusNotify(PADAPTER padapter, u8 mediaStatus)
{
    PHAL_DATA_TYPE    pHalData;
    pHalData = GET_HAL_DATA(padapter);
    if (_FALSE == pHalData->EEPROMBluetoothCoexist)
        return;
#ifdef DBG_CONFIG_ERROR_RESET
    if (_TRUE == rtw_hal_sreset_inprogress(padapter)) {
        RTW_INFO(FUNC_ADPT_FMT ": [BTCoex] under reset, skip notify!\n",
             FUNC_ADPT_ARG(padapter));
        return;
    }
#endif /* DBG_CONFIG_ERROR_RESET */
#ifdef CONFIG_CONCURRENT_MODE
    if (RT_MEDIA_DISCONNECT == mediaStatus) {
        if (rtw_mi_buddy_check_fwstate(padapter, WIFI_ASOC_STATE))
            return;
    }
#endif /* CONFIG_CONCURRENT_MODE */
    if ((RT_MEDIA_CONNECT == mediaStatus)
        && (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE))
        rtw_hal_set_hwreg(padapter, HW_VAR_DL_RSVD_PAGE, NULL);
    hal_btcoex_MediaStatusNotify(padapter, mediaStatus);
}
void rtw_btcoex_SpecialPacketNotify(PADAPTER padapter, u8 pktType)
{
    PHAL_DATA_TYPE    pHalData;
    pHalData = GET_HAL_DATA(padapter);
    if (_FALSE == pHalData->EEPROMBluetoothCoexist)
        return;
    hal_btcoex_SpecialPacketNotify(padapter, pktType);
}
void rtw_btcoex_IQKNotify(PADAPTER padapter, u8 state)
{
    PHAL_DATA_TYPE    pHalData;
    pHalData = GET_HAL_DATA(padapter);
    if (_FALSE == pHalData->EEPROMBluetoothCoexist)
        return;
    hal_btcoex_IQKNotify(padapter, state);
}
void rtw_btcoex_BtInfoNotify(PADAPTER padapter, u8 length, u8 *tmpBuf)
{
    PHAL_DATA_TYPE    pHalData;
    pHalData = GET_HAL_DATA(padapter);
    if (_FALSE == pHalData->EEPROMBluetoothCoexist)
        return;
    hal_btcoex_BtInfoNotify(padapter, length, tmpBuf);
}
void rtw_btcoex_BtMpRptNotify(PADAPTER padapter, u8 length, u8 *tmpBuf)
{
    PHAL_DATA_TYPE    pHalData;
    pHalData = GET_HAL_DATA(padapter);
    if (_FALSE == pHalData->EEPROMBluetoothCoexist)
        return;
    if (padapter->registrypriv.mp_mode == 1)
        return;
    hal_btcoex_BtMpRptNotify(padapter, length, tmpBuf);
}
void rtw_btcoex_SuspendNotify(PADAPTER padapter, u8 state)
{
    PHAL_DATA_TYPE    pHalData;
    pHalData = GET_HAL_DATA(padapter);
    if (_FALSE == pHalData->EEPROMBluetoothCoexist)
        return;
    hal_btcoex_SuspendNotify(padapter, state);
}
void rtw_btcoex_HaltNotify(PADAPTER padapter)
{
    PHAL_DATA_TYPE    pHalData;
    u8 do_halt = 1;
    pHalData = GET_HAL_DATA(padapter);
    if (_FALSE == pHalData->EEPROMBluetoothCoexist)
        do_halt = 0;
    if (_FALSE == padapter->bup) {
        RTW_INFO(FUNC_ADPT_FMT ": bup=%d Skip!\n",
             FUNC_ADPT_ARG(padapter), padapter->bup);
        do_halt = 0;
    }
    if (rtw_is_surprise_removed(padapter)) {
        RTW_INFO(FUNC_ADPT_FMT ": bSurpriseRemoved=%s Skip!\n",
            FUNC_ADPT_ARG(padapter), rtw_is_surprise_removed(padapter) ? "True" : "False");
        do_halt = 0;
    }
    hal_btcoex_HaltNotify(padapter, do_halt);
}
void rtw_btcoex_switchband_notify(u8 under_scan, u8 band_type)
{
    hal_btcoex_switchband_notify(under_scan, band_type);
}
void rtw_btcoex_SwitchBtTRxMask(PADAPTER padapter)
{
    hal_btcoex_SwitchBtTRxMask(padapter);
}
void rtw_btcoex_Switch(PADAPTER padapter, u8 enable)
{
    hal_btcoex_SetBTCoexist(padapter, enable);
}
u8 rtw_btcoex_IsBtDisabled(PADAPTER padapter)
{
    return hal_btcoex_IsBtDisabled(padapter);
}
void rtw_btcoex_Handler(PADAPTER padapter)
{
    PHAL_DATA_TYPE    pHalData;
    pHalData = GET_HAL_DATA(padapter);
    if (_FALSE == pHalData->EEPROMBluetoothCoexist)
        return;
    hal_btcoex_Hanlder(padapter);
}
s32 rtw_btcoex_IsBTCoexRejectAMPDU(PADAPTER padapter)
{
    s32 coexctrl;
    coexctrl = hal_btcoex_IsBTCoexRejectAMPDU(padapter);
    return coexctrl;
}
s32 rtw_btcoex_IsBTCoexCtrlAMPDUSize(PADAPTER padapter)
{
    s32 coexctrl;
    coexctrl = hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter);
    return coexctrl;
}
u32 rtw_btcoex_GetAMPDUSize(PADAPTER padapter)
{
    u32 size;
    size = hal_btcoex_GetAMPDUSize(padapter);
    return size;
}
void rtw_btcoex_SetManualControl(PADAPTER padapter, u8 manual)
{
    if (_TRUE == manual)
        hal_btcoex_SetManualControl(padapter, _TRUE);
    else
        hal_btcoex_SetManualControl(padapter, _FALSE);
}
u8 rtw_btcoex_1Ant(PADAPTER padapter)
{
    return hal_btcoex_1Ant(padapter);
}
u8 rtw_btcoex_IsBtControlLps(PADAPTER padapter)
{
    return hal_btcoex_IsBtControlLps(padapter);
}
u8 rtw_btcoex_IsLpsOn(PADAPTER padapter)
{
    return hal_btcoex_IsLpsOn(padapter);
}
u8 rtw_btcoex_RpwmVal(PADAPTER padapter)
{
    return hal_btcoex_RpwmVal(padapter);
}
u8 rtw_btcoex_LpsVal(PADAPTER padapter)
{
    return hal_btcoex_LpsVal(padapter);
}
u32 rtw_btcoex_GetRaMask(PADAPTER padapter)
{
    return hal_btcoex_GetRaMask(padapter);
}
void rtw_btcoex_RecordPwrMode(PADAPTER padapter, u8 *pCmdBuf, u8 cmdLen)
{
    hal_btcoex_RecordPwrMode(padapter, pCmdBuf, cmdLen);
}
void rtw_btcoex_DisplayBtCoexInfo(PADAPTER padapter, u8 *pbuf, u32 bufsize)
{
    hal_btcoex_DisplayBtCoexInfo(padapter, pbuf, bufsize);
}
void rtw_btcoex_SetDBG(PADAPTER padapter, u32 *pDbgModule)
{
    hal_btcoex_SetDBG(padapter, pDbgModule);
}
u32 rtw_btcoex_GetDBG(PADAPTER padapter, u8 *pStrBuf, u32 bufSize)
{
    return hal_btcoex_GetDBG(padapter, pStrBuf, bufSize);
}
u8 rtw_btcoex_IncreaseScanDeviceNum(PADAPTER padapter)
{
    return hal_btcoex_IncreaseScanDeviceNum(padapter);
}
u8 rtw_btcoex_IsBtLinkExist(PADAPTER padapter)
{
    return hal_btcoex_IsBtLinkExist(padapter);
}
void rtw_btcoex_SetBtPatchVersion(PADAPTER padapter, u16 btHciVer, u16 btPatchVer)
{
    hal_btcoex_SetBtPatchVersion(padapter, btHciVer, btPatchVer);
}
void rtw_btcoex_SetHciVersion(PADAPTER  padapter, u16 hciVersion)
{
    hal_btcoex_SetHciVersion(padapter, hciVersion);
}
void rtw_btcoex_StackUpdateProfileInfo(void)
{
    hal_btcoex_StackUpdateProfileInfo();
}
void rtw_btcoex_pta_off_on_notify(PADAPTER padapter, u8 bBTON)
{
    hal_btcoex_pta_off_on_notify(padapter, bBTON);
}
/* ==================================================
 * Below Functions are called by BT-Coex
 * ================================================== */
void rtw_btcoex_rx_ampdu_apply(PADAPTER padapter)
{
    rtw_rx_ampdu_apply(padapter);
}
void rtw_btcoex_LPS_Enter(PADAPTER padapter)
{
    struct pwrctrl_priv *pwrpriv;
    u8 lpsVal;
    pwrpriv = adapter_to_pwrctl(padapter);
    pwrpriv->bpower_saving = _TRUE;
    lpsVal = rtw_btcoex_LpsVal(padapter);
    rtw_set_ps_mode(padapter, PS_MODE_MIN, 0, lpsVal, "BTCOEX");
}
void rtw_btcoex_LPS_Leave(PADAPTER padapter)
{
    struct pwrctrl_priv *pwrpriv;
    pwrpriv = adapter_to_pwrctl(padapter);
    if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
        rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, "BTCOEX");
        LPS_RF_ON_check(padapter, 100);
        pwrpriv->bpower_saving = _FALSE;
    }
}
u16 rtw_btcoex_btreg_read(PADAPTER padapter, u8 type, u16 addr, u32 *data)
{
    return hal_btcoex_btreg_read(padapter, type, addr, data);
}
u16 rtw_btcoex_btreg_write(PADAPTER padapter, u8 type, u16 addr, u16 val)
{
    return hal_btcoex_btreg_write(padapter, type, addr, val);
}
u8 rtw_btcoex_get_bt_coexist(PADAPTER padapter)
{
    HAL_DATA_TYPE    *pHalData = GET_HAL_DATA(padapter);
    return pHalData->EEPROMBluetoothCoexist;
}
u8 rtw_btcoex_get_chip_type(PADAPTER padapter)
{
    HAL_DATA_TYPE    *pHalData = GET_HAL_DATA(padapter);
    return pHalData->EEPROMBluetoothType;
}
u8 rtw_btcoex_get_pg_ant_num(PADAPTER padapter)
{
    HAL_DATA_TYPE    *pHalData = GET_HAL_DATA(padapter);
    return pHalData->EEPROMBluetoothAntNum == Ant_x2 ? 2 : 1;
}
u8 rtw_btcoex_get_pg_single_ant_path(PADAPTER padapter)
{
    HAL_DATA_TYPE    *pHalData = GET_HAL_DATA(padapter);
    return pHalData->ant_path;
}
u8 rtw_btcoex_get_pg_rfe_type(PADAPTER padapter)
{
    HAL_DATA_TYPE    *pHalData = GET_HAL_DATA(padapter);
    return pHalData->rfe_type;
}
u8 rtw_btcoex_is_tfbga_package_type(PADAPTER padapter)
{
    HAL_DATA_TYPE    *pHalData = GET_HAL_DATA(padapter);
#ifdef CONFIG_RTL8723B
    if ((pHalData->PackageType == PACKAGE_TFBGA79) || (pHalData->PackageType == PACKAGE_TFBGA80)
        || (pHalData->PackageType == PACKAGE_TFBGA90))
        return _TRUE;
#endif
    return _FALSE;
}
u8 rtw_btcoex_get_ant_div_cfg(PADAPTER padapter)
{
    PHAL_DATA_TYPE pHalData;
    pHalData = GET_HAL_DATA(padapter);
    return (pHalData->AntDivCfg == 0) ? _FALSE : _TRUE;
}
/* ==================================================
 * Below Functions are BT-Coex socket related function
 * ================================================== */
#ifdef CONFIG_BT_COEXIST_SOCKET_TRX
_adapter *pbtcoexadapter; /* = NULL; */ /* do not initialise globals to 0 or NULL */
u8 rtw_btcoex_btinfo_cmd(_adapter *adapter, u8 *buf, u16 len)
{
    struct cmd_obj *ph2c;
    struct drvextra_cmd_parm *pdrvextra_cmd_parm;
    u8 *btinfo;
    struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
    u8    res = _SUCCESS;
    ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
    if (ph2c == NULL) {
        res = _FAIL;
        goto exit;
    }
    pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
    if (pdrvextra_cmd_parm == NULL) {
        rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
        res = _FAIL;
        goto exit;
    }
    btinfo = rtw_zmalloc(len);
    if (btinfo == NULL) {
        rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
        rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
        res = _FAIL;
        goto exit;
    }
    pdrvextra_cmd_parm->ec_id = BTINFO_WK_CID;
    pdrvextra_cmd_parm->type = 0;
    pdrvextra_cmd_parm->size = len;
    pdrvextra_cmd_parm->pbuf = btinfo;
    _rtw_memcpy(btinfo, buf, len);
    init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
    res = rtw_enqueue_cmd(pcmdpriv, ph2c);
exit:
    return res;
}
u8 rtw_btcoex_send_event_to_BT(_adapter *padapter, u8 status,  u8 event_code, u8 opcode_low, u8 opcode_high, u8 *dbg_msg)
{
    u8 localBuf[6] = "";
    u8 *pRetPar;
    u8    len = 0, tx_event_length = 0;
    rtw_HCI_event *pEvent;
    pEvent = (rtw_HCI_event *)(&localBuf[0]);
    pEvent->EventCode = event_code;
    pEvent->Data[0] = 0x1;    /* packet # */
    pEvent->Data[1] = opcode_low;
    pEvent->Data[2] = opcode_high;
    len = len + 3;
    /* Return parameters starts from here */
    pRetPar = &pEvent->Data[len];
    pRetPar[0] = status;        /* status */
    len++;
    pEvent->Length = len;
    /* total tx event length + EventCode length + sizeof(length) */
    tx_event_length = pEvent->Length + 2;
#if 0
    rtw_btcoex_dump_tx_msg((u8 *)pEvent, tx_event_length, dbg_msg);
#endif
    status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
    return status;
}
/*
Ref:
Realtek Wi-Fi Driver
Host Controller Interface for
Bluetooth 3.0 + HS V1.4 2013/02/07
Window team code & BT team code
 */
u8 rtw_btcoex_parse_BT_info_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
{
#define BT_INFO_LENGTH 8
    u8 curPollEnable = pcmd[0];
    u8 curPollTime = pcmd[1];
    u8 btInfoReason = pcmd[2];
    u8 btInfoLen = pcmd[3];
    u8 btinfo[BT_INFO_LENGTH];
    u8 localBuf[6] = "";
    u8 *pRetPar;
    u8    len = 0, tx_event_length = 0;
    RTW_HCI_STATUS status = HCI_STATUS_SUCCESS;
    rtw_HCI_event *pEvent;
    /* RTW_INFO("%s\n",__func__);
    RTW_INFO("current Poll Enable: %d, currrent Poll Time: %d\n",curPollEnable,curPollTime);
    RTW_INFO("BT Info reason: %d, BT Info length: %d\n",btInfoReason,btInfoLen);
    RTW_INFO("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n"
        ,pcmd[4],pcmd[5],pcmd[6],pcmd[7],pcmd[8],pcmd[9],pcmd[10],pcmd[11]);*/
    _rtw_memset(btinfo, 0, BT_INFO_LENGTH);
#if 1
    if (BT_INFO_LENGTH != btInfoLen) {
        status = HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE;
        RTW_INFO("Error BT Info Length: %d\n", btInfoLen);
        /* return _FAIL; */
    } else
#endif
    {
        if (0x1 == btInfoReason || 0x2 == btInfoReason) {
            _rtw_memcpy(btinfo, &pcmd[4], btInfoLen);
            btinfo[0] = btInfoReason;
            rtw_btcoex_btinfo_cmd(padapter, btinfo, btInfoLen);
        } else
            RTW_INFO("Other BT info reason\n");
    }
    /* send complete event to BT */
    {
        pEvent = (rtw_HCI_event *)(&localBuf[0]);
        pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
        pEvent->Data[0] = 0x1;    /* packet # */
        pEvent->Data[1] = HCIOPCODELOW(HCI_BT_INFO_NOTIFY, OGF_EXTENSION);
        pEvent->Data[2] = HCIOPCODEHIGHT(HCI_BT_INFO_NOTIFY, OGF_EXTENSION);
        len = len + 3;
        /* Return parameters starts from here */
        pRetPar = &pEvent->Data[len];
        pRetPar[0] = status;        /* status */
        len++;
        pEvent->Length = len;
        /* total tx event length + EventCode length + sizeof(length) */
        tx_event_length = pEvent->Length + 2;
#if 0
        rtw_btcoex_dump_tx_msg((u8 *)pEvent, tx_event_length, "BT_info_event");
#endif
        status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
        return status;
        /* bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2); */
    }
}
u8 rtw_btcoex_parse_BT_patch_ver_info_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
{
    RTW_HCI_STATUS status = HCI_STATUS_SUCCESS;
    u16        btPatchVer = 0x0, btHciVer = 0x0;
    /* u16        *pU2tmp; */
    u8 localBuf[6] = "";
    u8 *pRetPar;
    u8    len = 0, tx_event_length = 0;
    rtw_HCI_event *pEvent;
    btHciVer = pcmd[0] | pcmd[1] << 8;
    btPatchVer = pcmd[2] | pcmd[3] << 8;
    RTW_INFO("%s, cmd:%02x %02x %02x %02x\n", __func__, pcmd[0] , pcmd[1] , pcmd[2] , pcmd[3]);
    RTW_INFO("%s, HCI Ver:%d, Patch Ver:%d\n", __func__, btHciVer, btPatchVer);
    rtw_btcoex_SetBtPatchVersion(padapter, btHciVer, btPatchVer);
    /* send complete event to BT */
    {
        pEvent = (rtw_HCI_event *)(&localBuf[0]);
        pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
        pEvent->Data[0] = 0x1;    /* packet # */
        pEvent->Data[1] = HCIOPCODELOW(HCI_BT_PATCH_VERSION_NOTIFY, OGF_EXTENSION);
        pEvent->Data[2] = HCIOPCODEHIGHT(HCI_BT_PATCH_VERSION_NOTIFY, OGF_EXTENSION);
        len = len + 3;
        /* Return parameters starts from here */
        pRetPar = &pEvent->Data[len];
        pRetPar[0] = status;        /* status */
        len++;
        pEvent->Length = len;
        /* total tx event length + EventCode length + sizeof(length) */
        tx_event_length = pEvent->Length + 2;
#if 0
        rtw_btcoex_dump_tx_msg((u8 *)pEvent, tx_event_length, "BT_patch_event");
#endif
        status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
        return status;
        /* bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2); */
    }
}
u8 rtw_btcoex_parse_HCI_Ver_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
{
    RTW_HCI_STATUS status = HCI_STATUS_SUCCESS;
    u16 hciver = pcmd[0] | pcmd[1] << 8;
    u8 localBuf[6] = "";
    u8 *pRetPar;
    u8    len = 0, tx_event_length = 0;
    rtw_HCI_event *pEvent;
    struct bt_coex_info *pcoex_info = &padapter->coex_info;
    PBT_MGNT    pBtMgnt = &pcoex_info->BtMgnt;
    pBtMgnt->ExtConfig.HCIExtensionVer = hciver;
    RTW_INFO("%s, HCI Version: %d\n", __func__, pBtMgnt->ExtConfig.HCIExtensionVer);
    if (pBtMgnt->ExtConfig.HCIExtensionVer  < 4) {
        status = HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE;
        RTW_INFO("%s, Version = %d, HCI Version < 4\n", __func__, pBtMgnt->ExtConfig.HCIExtensionVer);
    } else
        rtw_btcoex_SetHciVersion(padapter, hciver);
    /* send complete event to BT */
    {
        pEvent = (rtw_HCI_event *)(&localBuf[0]);
        pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
        pEvent->Data[0] = 0x1;    /* packet # */
        pEvent->Data[1] = HCIOPCODELOW(HCI_EXTENSION_VERSION_NOTIFY, OGF_EXTENSION);
        pEvent->Data[2] = HCIOPCODEHIGHT(HCI_EXTENSION_VERSION_NOTIFY, OGF_EXTENSION);
        len = len + 3;
        /* Return parameters starts from here */
        pRetPar = &pEvent->Data[len];
        pRetPar[0] = status;        /* status */
        len++;
        pEvent->Length = len;
        /* total tx event length + EventCode length + sizeof(length) */
        tx_event_length = pEvent->Length + 2;
        status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
        return status;
        /* bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2); */
    }
}
u8 rtw_btcoex_parse_WIFI_scan_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
{
    RTW_HCI_STATUS status = HCI_STATUS_SUCCESS;
    u8 localBuf[6] = "";
    u8 *pRetPar;
    u8    len = 0, tx_event_length = 0;
    rtw_HCI_event *pEvent;
    struct bt_coex_info *pcoex_info = &padapter->coex_info;
    PBT_MGNT    pBtMgnt = &pcoex_info->BtMgnt;
    pBtMgnt->ExtConfig.bEnableWifiScanNotify = pcmd[0];
    RTW_INFO("%s, bEnableWifiScanNotify: %d\n", __func__, pBtMgnt->ExtConfig.bEnableWifiScanNotify);
    /* send complete event to BT */
    {
        pEvent = (rtw_HCI_event *)(&localBuf[0]);
        pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
        pEvent->Data[0] = 0x1;    /* packet # */
        pEvent->Data[1] = HCIOPCODELOW(HCI_ENABLE_WIFI_SCAN_NOTIFY, OGF_EXTENSION);
        pEvent->Data[2] = HCIOPCODEHIGHT(HCI_ENABLE_WIFI_SCAN_NOTIFY, OGF_EXTENSION);
        len = len + 3;
        /* Return parameters starts from here */
        pRetPar = &pEvent->Data[len];
        pRetPar[0] = status;        /* status */
        len++;
        pEvent->Length = len;
        /* total tx event length + EventCode length + sizeof(length) */
        tx_event_length = pEvent->Length + 2;
        status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
        return status;
        /* bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2); */
    }
}
u8 rtw_btcoex_parse_HCI_link_status_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
{
    RTW_HCI_STATUS    status = HCI_STATUS_SUCCESS;
    struct bt_coex_info    *pcoex_info = &padapter->coex_info;
    PBT_MGNT    pBtMgnt = &pcoex_info->BtMgnt;
    /* PBT_DBG        pBtDbg=&padapter->MgntInfo.BtInfo.BtDbg; */
    u8        i, numOfHandle = 0, numOfAcl = 0;
    u16        conHandle;
    u8        btProfile, btCoreSpec, linkRole;
    u8        *pTriple;
    u8 localBuf[6] = "";
    u8 *pRetPar;
    u8    len = 0, tx_event_length = 0;
    rtw_HCI_event *pEvent;
    /* pBtDbg->dbgHciInfo.hciCmdCntLinkStatusNotify++; */
    /* RT_DISP_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "LinkStatusNotify, Hex Data :\n",  */
    /*        &pHciCmd->Data[0], pHciCmd->Length); */
    RTW_INFO("BTLinkStatusNotify\n");
    /* Current only RTL8723 support this command. */
    /* pBtMgnt->bSupportProfile = TRUE; */
    pBtMgnt->bSupportProfile = _FALSE;
    pBtMgnt->ExtConfig.NumberOfACL = 0;
    pBtMgnt->ExtConfig.NumberOfSCO = 0;
    numOfHandle = pcmd[0];
    /* RT_DISP(FIOCTL, IOCTL_BT_HCICMD_EXT, ("numOfHandle = 0x%x\n", numOfHandle)); */
    /* RT_DISP(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCIExtensionVer = %d\n", pBtMgnt->ExtConfig.HCIExtensionVer)); */
    RTW_INFO("numOfHandle = 0x%x\n", numOfHandle);
    RTW_INFO("HCIExtensionVer = %d\n", pBtMgnt->ExtConfig.HCIExtensionVer);
    pTriple = &pcmd[1];
    for (i = 0; i < numOfHandle; i++) {
        if (pBtMgnt->ExtConfig.HCIExtensionVer < 1) {
            conHandle = *((u8 *)&pTriple[0]);
            btProfile = pTriple[2];
            btCoreSpec = pTriple[3];
            if (BT_PROFILE_SCO == btProfile)
                pBtMgnt->ExtConfig.NumberOfSCO++;
            else {
                pBtMgnt->ExtConfig.NumberOfACL++;
                pBtMgnt->ExtConfig.aclLink[i].ConnectHandle = conHandle;
                pBtMgnt->ExtConfig.aclLink[i].BTProfile = btProfile;
                pBtMgnt->ExtConfig.aclLink[i].BTCoreSpec = btCoreSpec;
            }
            /* RT_DISP(FIOCTL, IOCTL_BT_HCICMD_EXT, */
            /*    ("Connection_Handle=0x%x, BTProfile=%d, BTSpec=%d\n", */
            /*        conHandle, btProfile, btCoreSpec)); */
            RTW_INFO("Connection_Handle=0x%x, BTProfile=%d, BTSpec=%d\n", conHandle, btProfile, btCoreSpec);
            pTriple += 4;
        } else if (pBtMgnt->ExtConfig.HCIExtensionVer >= 1) {
            conHandle = *((pu2Byte)&pTriple[0]);
            btProfile = pTriple[2];
            btCoreSpec = pTriple[3];
            linkRole = pTriple[4];
            if (BT_PROFILE_SCO == btProfile)
                pBtMgnt->ExtConfig.NumberOfSCO++;
            else {
                pBtMgnt->ExtConfig.NumberOfACL++;
                pBtMgnt->ExtConfig.aclLink[i].ConnectHandle = conHandle;
                pBtMgnt->ExtConfig.aclLink[i].BTProfile = btProfile;
                pBtMgnt->ExtConfig.aclLink[i].BTCoreSpec = btCoreSpec;
                pBtMgnt->ExtConfig.aclLink[i].linkRole = linkRole;
            }
            /* RT_DISP(FIOCTL, IOCTL_BT_HCICMD_EXT, */
            RTW_INFO("Connection_Handle=0x%x, BTProfile=%d, BTSpec=%d, LinkRole=%d\n",
                 conHandle, btProfile, btCoreSpec, linkRole);
            pTriple += 5;
        }
    }
    rtw_btcoex_StackUpdateProfileInfo();
    /* send complete event to BT */
    {
        pEvent = (rtw_HCI_event *)(&localBuf[0]);
        pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
        pEvent->Data[0] = 0x1;    /* packet # */
        pEvent->Data[1] = HCIOPCODELOW(HCI_LINK_STATUS_NOTIFY, OGF_EXTENSION);
        pEvent->Data[2] = HCIOPCODEHIGHT(HCI_LINK_STATUS_NOTIFY, OGF_EXTENSION);
        len = len + 3;
        /* Return parameters starts from here */
        pRetPar = &pEvent->Data[len];
        pRetPar[0] = status;        /* status */
        len++;
        pEvent->Length = len;
        /* total tx event length + EventCode length + sizeof(length) */
        tx_event_length = pEvent->Length + 2;
        status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
        return status;
        /* bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2); */
    }
}
u8 rtw_btcoex_parse_HCI_BT_coex_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
{
    u8 localBuf[6] = "";
    u8 *pRetPar;
    u8    len = 0, tx_event_length = 0;
    rtw_HCI_event *pEvent;
    RTW_HCI_STATUS    status = HCI_STATUS_SUCCESS;
    {
        pEvent = (rtw_HCI_event *)(&localBuf[0]);
        pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
        pEvent->Data[0] = 0x1;    /* packet # */
        pEvent->Data[1] = HCIOPCODELOW(HCI_BT_COEX_NOTIFY, OGF_EXTENSION);
        pEvent->Data[2] = HCIOPCODEHIGHT(HCI_BT_COEX_NOTIFY, OGF_EXTENSION);
        len = len + 3;
        /* Return parameters starts from here */
        pRetPar = &pEvent->Data[len];
        pRetPar[0] = status;        /* status */
        len++;
        pEvent->Length = len;
        /* total tx event length + EventCode length + sizeof(length) */
        tx_event_length = pEvent->Length + 2;
        status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
        return status;
        /* bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2); */
    }
}
u8 rtw_btcoex_parse_HCI_BT_operation_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
{
    u8 localBuf[6] = "";
    u8 *pRetPar;
    u8    len = 0, tx_event_length = 0;
    rtw_HCI_event *pEvent;
    RTW_HCI_STATUS    status = HCI_STATUS_SUCCESS;
    RTW_INFO("%s, OP code: %d\n", __func__, pcmd[0]);
    switch (pcmd[0]) {
    case HCI_BT_OP_NONE:
        RTW_INFO("[bt operation] : Operation None!!\n");
        break;
    case HCI_BT_OP_INQUIRY_START:
        RTW_INFO("[bt operation] : Inquiry start!!\n");
        break;
    case HCI_BT_OP_INQUIRY_FINISH:
        RTW_INFO("[bt operation] : Inquiry finished!!\n");
        break;
    case HCI_BT_OP_PAGING_START:
        RTW_INFO("[bt operation] : Paging is started!!\n");
        break;
    case HCI_BT_OP_PAGING_SUCCESS:
        RTW_INFO("[bt operation] : Paging complete successfully!!\n");
        break;
    case HCI_BT_OP_PAGING_UNSUCCESS:
        RTW_INFO("[bt operation] : Paging complete unsuccessfully!!\n");
        break;
    case HCI_BT_OP_PAIRING_START:
        RTW_INFO("[bt operation] : Pairing start!!\n");
        break;
    case HCI_BT_OP_PAIRING_FINISH:
        RTW_INFO("[bt operation] : Pairing finished!!\n");
        break;
    case HCI_BT_OP_BT_DEV_ENABLE:
        RTW_INFO("[bt operation] : BT Device is enabled!!\n");
        break;
    case HCI_BT_OP_BT_DEV_DISABLE:
        RTW_INFO("[bt operation] : BT Device is disabled!!\n");
        break;
    default:
        RTW_INFO("[bt operation] : Unknown, error!!\n");
        break;
    }
    /* send complete event to BT */
    {
        pEvent = (rtw_HCI_event *)(&localBuf[0]);
        pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
        pEvent->Data[0] = 0x1;    /* packet # */
        pEvent->Data[1] = HCIOPCODELOW(HCI_BT_OPERATION_NOTIFY, OGF_EXTENSION);
        pEvent->Data[2] = HCIOPCODEHIGHT(HCI_BT_OPERATION_NOTIFY, OGF_EXTENSION);
        len = len + 3;
        /* Return parameters starts from here */
        pRetPar = &pEvent->Data[len];
        pRetPar[0] = status;        /* status */
        len++;
        pEvent->Length = len;
        /* total tx event length + EventCode length + sizeof(length) */
        tx_event_length = pEvent->Length + 2;
        status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
        return status;
        /* bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2); */
    }
}
u8 rtw_btcoex_parse_BT_AFH_MAP_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
{
    u8 localBuf[6] = "";
    u8 *pRetPar;
    u8    len = 0, tx_event_length = 0;
    rtw_HCI_event *pEvent;
    RTW_HCI_STATUS    status = HCI_STATUS_SUCCESS;
    {
        pEvent = (rtw_HCI_event *)(&localBuf[0]);
        pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
        pEvent->Data[0] = 0x1;    /* packet # */
        pEvent->Data[1] = HCIOPCODELOW(HCI_BT_AFH_MAP_NOTIFY, OGF_EXTENSION);
        pEvent->Data[2] = HCIOPCODEHIGHT(HCI_BT_AFH_MAP_NOTIFY, OGF_EXTENSION);
        len = len + 3;
        /* Return parameters starts from here */
        pRetPar = &pEvent->Data[len];
        pRetPar[0] = status;        /* status */
        len++;
        pEvent->Length = len;
        /* total tx event length + EventCode length + sizeof(length) */
        tx_event_length = pEvent->Length + 2;
        status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
        return status;
        /* bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2); */
    }
}
u8 rtw_btcoex_parse_BT_register_val_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
{
    u8 localBuf[6] = "";
    u8 *pRetPar;
    u8    len = 0, tx_event_length = 0;
    rtw_HCI_event *pEvent;
    RTW_HCI_STATUS    status = HCI_STATUS_SUCCESS;
    {
        pEvent = (rtw_HCI_event *)(&localBuf[0]);
        pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
        pEvent->Data[0] = 0x1;    /* packet # */
        pEvent->Data[1] = HCIOPCODELOW(HCI_BT_REGISTER_VALUE_NOTIFY, OGF_EXTENSION);
        pEvent->Data[2] = HCIOPCODEHIGHT(HCI_BT_REGISTER_VALUE_NOTIFY, OGF_EXTENSION);
        len = len + 3;
        /* Return parameters starts from here */
        pRetPar = &pEvent->Data[len];
        pRetPar[0] = status;        /* status */
        len++;
        pEvent->Length = len;
        /* total tx event length + EventCode length + sizeof(length) */
        tx_event_length = pEvent->Length + 2;
        status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
        return status;
        /* bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2); */
    }
}
u8 rtw_btcoex_parse_HCI_BT_abnormal_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
{
    u8 localBuf[6] = "";
    u8 *pRetPar;
    u8    len = 0, tx_event_length = 0;
    rtw_HCI_event *pEvent;
    RTW_HCI_STATUS    status = HCI_STATUS_SUCCESS;
    {
        pEvent = (rtw_HCI_event *)(&localBuf[0]);
        pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
        pEvent->Data[0] = 0x1;    /* packet # */
        pEvent->Data[1] = HCIOPCODELOW(HCI_BT_ABNORMAL_NOTIFY, OGF_EXTENSION);
        pEvent->Data[2] = HCIOPCODEHIGHT(HCI_BT_ABNORMAL_NOTIFY, OGF_EXTENSION);
        len = len + 3;
        /* Return parameters starts from here */
        pRetPar = &pEvent->Data[len];
        pRetPar[0] = status;        /* status */
        len++;
        pEvent->Length = len;
        /* total tx event length + EventCode length + sizeof(length) */
        tx_event_length = pEvent->Length + 2;
        status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
        return status;
        /* bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2); */
    }
}
u8 rtw_btcoex_parse_HCI_query_RF_status_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
{
    u8 localBuf[6] = "";
    u8 *pRetPar;
    u8    len = 0, tx_event_length = 0;
    rtw_HCI_event *pEvent;
    RTW_HCI_STATUS    status = HCI_STATUS_SUCCESS;
    {
        pEvent = (rtw_HCI_event *)(&localBuf[0]);
        pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
        pEvent->Data[0] = 0x1;    /* packet # */
        pEvent->Data[1] = HCIOPCODELOW(HCI_QUERY_RF_STATUS, OGF_EXTENSION);
        pEvent->Data[2] = HCIOPCODEHIGHT(HCI_QUERY_RF_STATUS, OGF_EXTENSION);
        len = len + 3;
        /* Return parameters starts from here */
        pRetPar = &pEvent->Data[len];
        pRetPar[0] = status;        /* status */
        len++;
        pEvent->Length = len;
        /* total tx event length + EventCode length + sizeof(length) */
        tx_event_length = pEvent->Length + 2;
        status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
        return status;
        /* bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2); */
    }
}
/*****************************************
* HCI cmd format :
*| 15 - 0                        |
*| OPcode (OCF|OGF<<10)        |
*| 15 - 8        |7 - 0            |
*|Cmd para    |Cmd para Length    |
*|Cmd para......                |
******************************************/
/* bit 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
 *     |    OCF                         |       OGF       | */
void rtw_btcoex_parse_hci_extend_cmd(_adapter *padapter, u8 *pcmd, u16 len, const u16 hci_OCF)
{
    RTW_INFO("%s: OCF: %x\n", __func__, hci_OCF);
    switch (hci_OCF) {
    case HCI_EXTENSION_VERSION_NOTIFY:
        RTW_INFO("HCI_EXTENSION_VERSION_NOTIFY\n");
        rtw_btcoex_parse_HCI_Ver_notify_cmd(padapter, pcmd, len);
        break;
    case HCI_LINK_STATUS_NOTIFY:
        RTW_INFO("HCI_LINK_STATUS_NOTIFY\n");
        rtw_btcoex_parse_HCI_link_status_notify_cmd(padapter, pcmd, len);
        break;
    case HCI_BT_OPERATION_NOTIFY:
        /* only for 8723a 2ant */
        RTW_INFO("HCI_BT_OPERATION_NOTIFY\n");
        rtw_btcoex_parse_HCI_BT_operation_notify_cmd(padapter, pcmd, len);
        /*  */
        break;
    case HCI_ENABLE_WIFI_SCAN_NOTIFY:
        RTW_INFO("HCI_ENABLE_WIFI_SCAN_NOTIFY\n");
        rtw_btcoex_parse_WIFI_scan_notify_cmd(padapter, pcmd, len);
        break;
    case HCI_QUERY_RF_STATUS:
        /* only for 8723b 2ant */
        RTW_INFO("HCI_QUERY_RF_STATUS\n");
        rtw_btcoex_parse_HCI_query_RF_status_cmd(padapter, pcmd, len);
        break;
    case HCI_BT_ABNORMAL_NOTIFY:
        RTW_INFO("HCI_BT_ABNORMAL_NOTIFY\n");
        rtw_btcoex_parse_HCI_BT_abnormal_notify_cmd(padapter, pcmd, len);
        break;
    case HCI_BT_INFO_NOTIFY:
        RTW_INFO("HCI_BT_INFO_NOTIFY\n");
        rtw_btcoex_parse_BT_info_notify_cmd(padapter, pcmd, len);
        break;
    case HCI_BT_COEX_NOTIFY:
        RTW_INFO("HCI_BT_COEX_NOTIFY\n");
        rtw_btcoex_parse_HCI_BT_coex_notify_cmd(padapter, pcmd, len);
        break;
    case HCI_BT_PATCH_VERSION_NOTIFY:
        RTW_INFO("HCI_BT_PATCH_VERSION_NOTIFY\n");
        rtw_btcoex_parse_BT_patch_ver_info_cmd(padapter, pcmd, len);
        break;
    case HCI_BT_AFH_MAP_NOTIFY:
        RTW_INFO("HCI_BT_AFH_MAP_NOTIFY\n");
        rtw_btcoex_parse_BT_AFH_MAP_notify_cmd(padapter, pcmd, len);
        break;
    case HCI_BT_REGISTER_VALUE_NOTIFY:
        RTW_INFO("HCI_BT_REGISTER_VALUE_NOTIFY\n");
        rtw_btcoex_parse_BT_register_val_notify_cmd(padapter, pcmd, len);
        break;
    default:
        RTW_INFO("ERROR!!! Unknown OCF: %x\n", hci_OCF);
        break;
    }
}
void rtw_btcoex_parse_hci_cmd(_adapter *padapter, u8 *pcmd, u16 len)
{
    u16 opcode = pcmd[0] | pcmd[1] << 8;
    u16 hci_OGF = HCI_OGF(opcode);
    u16 hci_OCF = HCI_OCF(opcode);
    u8 cmdlen = len - 3;
    u8 pare_len = pcmd[2];
    RTW_INFO("%s OGF: %x,OCF: %x\n", __func__, hci_OGF, hci_OCF);
    switch (hci_OGF) {
    case OGF_EXTENSION:
        RTW_INFO("HCI_EXTENSION_CMD_OGF\n");
        rtw_btcoex_parse_hci_extend_cmd(padapter, &pcmd[3], cmdlen, hci_OCF);
        break;
    default:
        RTW_INFO("Other OGF: %x\n", hci_OGF);
        break;
    }
}
u16 rtw_btcoex_parse_recv_data(u8 *msg, u8 msg_size)
{
    u8 cmp_msg1[32] = attend_ack;
    u8 cmp_msg2[32] = leave_ack;
    u8 cmp_msg3[32] = bt_leave;
    u8 cmp_msg4[32] = invite_req;
    u8 cmp_msg5[32] = attend_req;
    u8 cmp_msg6[32] = invite_rsp;
    u8 res = OTHER;
    if (_rtw_memcmp(cmp_msg1, msg, msg_size) == _TRUE) {
        /*RTW_INFO("%s, msg:%s\n",__func__,msg);*/
        res = RX_ATTEND_ACK;
    } else if (_rtw_memcmp(cmp_msg2, msg, msg_size) == _TRUE) {
        /*RTW_INFO("%s, msg:%s\n",__func__,msg);*/
        res = RX_LEAVE_ACK;
    } else if (_rtw_memcmp(cmp_msg3, msg, msg_size) == _TRUE) {
        /*RTW_INFO("%s, msg:%s\n",__func__,msg);*/
        res = RX_BT_LEAVE;
    } else if (_rtw_memcmp(cmp_msg4, msg, msg_size) == _TRUE) {
        /*RTW_INFO("%s, msg:%s\n",__func__,msg);*/
        res = RX_INVITE_REQ;
    } else if (_rtw_memcmp(cmp_msg5, msg, msg_size) == _TRUE)
        res = RX_ATTEND_REQ;
    else if (_rtw_memcmp(cmp_msg6, msg, msg_size) == _TRUE)
        res = RX_INVITE_RSP;
    else {
        /*RTW_INFO("%s, %s\n", __func__, msg);*/
        res = OTHER;
    }
    /*RTW_INFO("%s, res:%d\n", __func__, res);*/
    return res;
}
void rtw_btcoex_recvmsgbysocket(void *data)
{
    u8 recv_data[255];
    u8 tx_msg[255] = leave_ack;
    u32 len = 0;
    u16 recv_length = 0;
    u16 parse_res = 0;
#if 0
    u8 para_len = 0, polling_enable = 0, poling_interval = 0, reason = 0, btinfo_len = 0;
    u8 btinfo[BT_INFO_LEN] = {0};
#endif
    struct bt_coex_info *pcoex_info = NULL;
    struct sock *sk = NULL;
    struct sk_buff *skb = NULL;
    /*RTW_INFO("%s\n",__func__);*/
    if (pbtcoexadapter == NULL) {
        RTW_INFO("%s: btcoexadapter NULL!\n", __func__);
        return;
    }
    pcoex_info = &pbtcoexadapter->coex_info;
    sk = pcoex_info->sk_store;
    if (sk == NULL) {
        RTW_INFO("%s: critical error when receive socket data!\n", __func__);
        return;
    }
    len = skb_queue_len(&sk->sk_receive_queue);
    while (len > 0) {
        skb = skb_dequeue(&sk->sk_receive_queue);
        /*important: cut the udp header from skb->data! header length is 8 byte*/
        recv_length = skb->len - 8;
        _rtw_memset(recv_data, 0, sizeof(recv_data));
        _rtw_memcpy(recv_data, skb->data + 8, recv_length);
        parse_res = rtw_btcoex_parse_recv_data(recv_data, recv_length);
#if 0
        if (RX_ATTEND_ACK == parse_res) {
            /* attend ack */
            pcoex_info->BT_attend = _TRUE;
            RTW_INFO("RX_ATTEND_ACK!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
        } else if (RX_ATTEND_REQ == parse_res) {
            /* attend req from BT */
            pcoex_info->BT_attend = _TRUE;
            RTW_INFO("RX_BT_ATTEND_REQ!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
            rtw_btcoex_sendmsgbysocket(pbtcoexadapter, attend_ack, sizeof(attend_ack), _FALSE);
        } else if (RX_INVITE_REQ == parse_res) {
            /* invite req from BT */
            pcoex_info->BT_attend = _TRUE;
            RTW_INFO("RX_INVITE_REQ!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
            rtw_btcoex_sendmsgbysocket(pbtcoexadapter, invite_rsp, sizeof(invite_rsp), _FALSE);
        } else if (RX_INVITE_RSP == parse_res) {
            /* invite rsp */
            pcoex_info->BT_attend = _TRUE;
            RTW_INFO("RX_INVITE_RSP!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
        } else if (RX_LEAVE_ACK == parse_res) {
            /* mean BT know wifi  will leave */
            pcoex_info->BT_attend = _FALSE;
            RTW_INFO("RX_LEAVE_ACK!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
        } else if (RX_BT_LEAVE == parse_res) {
            /* BT leave */
            rtw_btcoex_sendmsgbysocket(pbtcoexadapter, leave_ack, sizeof(leave_ack), _FALSE); /*  no ack */
            pcoex_info->BT_attend = _FALSE;
            RTW_INFO("RX_BT_LEAVE!sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
        } else {
            /* todo: check if recv data are really hci cmds */
            if (_TRUE == pcoex_info->BT_attend)
                rtw_btcoex_parse_hci_cmd(pbtcoexadapter, recv_data, recv_length);
        }
#endif
        switch (parse_res) {
        case RX_ATTEND_ACK:
            /* attend ack */
            pcoex_info->BT_attend = _TRUE;
            RTW_INFO("RX_ATTEND_ACK!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
            rtw_btcoex_pta_off_on_notify(pbtcoexadapter, pcoex_info->BT_attend);
            break;
        case RX_ATTEND_REQ:
            pcoex_info->BT_attend = _TRUE;
            RTW_INFO("RX_BT_ATTEND_REQ!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
            rtw_btcoex_sendmsgbysocket(pbtcoexadapter, attend_ack, sizeof(attend_ack), _FALSE);
            rtw_btcoex_pta_off_on_notify(pbtcoexadapter, pcoex_info->BT_attend);
            break;
        case RX_INVITE_REQ:
            /* invite req from BT */
            pcoex_info->BT_attend = _TRUE;
            RTW_INFO("RX_INVITE_REQ!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
            rtw_btcoex_sendmsgbysocket(pbtcoexadapter, invite_rsp, sizeof(invite_rsp), _FALSE);
            rtw_btcoex_pta_off_on_notify(pbtcoexadapter, pcoex_info->BT_attend);
            break;
        case RX_INVITE_RSP:
            /*invite rsp*/
            pcoex_info->BT_attend = _TRUE;
            RTW_INFO("RX_INVITE_RSP!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
            rtw_btcoex_pta_off_on_notify(pbtcoexadapter, pcoex_info->BT_attend);
            break;
        case RX_LEAVE_ACK:
            /* mean BT know wifi  will leave */
            pcoex_info->BT_attend = _FALSE;
            RTW_INFO("RX_LEAVE_ACK!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
            rtw_btcoex_pta_off_on_notify(pbtcoexadapter, pcoex_info->BT_attend);
            break;
        case RX_BT_LEAVE:
            /* BT leave */
            rtw_btcoex_sendmsgbysocket(pbtcoexadapter, leave_ack, sizeof(leave_ack), _FALSE); /* no ack */
            pcoex_info->BT_attend = _FALSE;
            RTW_INFO("RX_BT_LEAVE!sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
            rtw_btcoex_pta_off_on_notify(pbtcoexadapter, pcoex_info->BT_attend);
            break;
        default:
            if (_TRUE == pcoex_info->BT_attend)
                rtw_btcoex_parse_hci_cmd(pbtcoexadapter, recv_data, recv_length);
            else
                RTW_INFO("ERROR!! BT is UP\n");
            break;
        }
        len--;
        kfree_skb(skb);
    }
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0))
    void rtw_btcoex_recvmsg_init(struct sock *sk_in, s32 bytes)
#else
    void rtw_btcoex_recvmsg_init(struct sock *sk_in)
#endif
{
    struct bt_coex_info *pcoex_info = NULL;
    if (pbtcoexadapter == NULL) {
        RTW_INFO("%s: btcoexadapter NULL\n", __func__);
        return;
    }
    pcoex_info = &pbtcoexadapter->coex_info;
    pcoex_info->sk_store = sk_in;
    if (pcoex_info->btcoex_wq != NULL)
        queue_delayed_work(pcoex_info->btcoex_wq, &pcoex_info->recvmsg_work, 0);
    else
        RTW_INFO("%s: BTCOEX workqueue NULL\n", __func__);
}
u8 rtw_btcoex_sendmsgbysocket(_adapter *padapter, u8 *msg, u8 msg_size, bool force)
{
    u8 error;
    struct msghdr    udpmsg;
    mm_segment_t    oldfs;
    struct iovec    iov;
    struct bt_coex_info *pcoex_info = &padapter->coex_info;
    /* RTW_INFO("%s: msg:%s, force:%s\n", __func__, msg, force == _TRUE?"TRUE":"FALSE"); */
    if (_FALSE == force) {
        if (_FALSE == pcoex_info->BT_attend) {
            RTW_INFO("TX Blocked: WiFi-BT disconnected\n");
            return _FAIL;
        }
    }
    iov.iov_base     = (void *)msg;
    iov.iov_len     = msg_size;
    udpmsg.msg_name     = &pcoex_info->bt_sockaddr;
    udpmsg.msg_namelen    = sizeof(struct sockaddr_in);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
    /* referece:sock_xmit in kernel code
     * WRITE for sock_sendmsg, READ for sock_recvmsg
     * third parameter for msg_iovlen
     * last parameter for iov_len
     */
    iov_iter_init(&udpmsg.msg_iter, WRITE, &iov, 1, msg_size);
#else
    udpmsg.msg_iov     = &iov;
    udpmsg.msg_iovlen    = 1;
#endif
    udpmsg.msg_control    = NULL;
    udpmsg.msg_controllen = 0;
    udpmsg.msg_flags    = MSG_DONTWAIT | MSG_NOSIGNAL;
    oldfs = get_fs();
    set_fs(KERNEL_DS);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
    error = sock_sendmsg(pcoex_info->udpsock, &udpmsg);
#else
    error = sock_sendmsg(pcoex_info->udpsock, &udpmsg, msg_size);
#endif
    set_fs(oldfs);
    if (error < 0) {
        RTW_INFO("Error when sendimg msg, error:%d\n", error);
        return _FAIL;
    } else
        return _SUCCESS;
}
u8 rtw_btcoex_create_kernel_socket(_adapter *padapter)
{
    s8 kernel_socket_err;
    u8 tx_msg[255] = attend_req;
    struct bt_coex_info *pcoex_info = &padapter->coex_info;
    s32 sock_reuse = 1;
    u8 status = _FAIL;
    RTW_INFO("%s CONNECT_PORT %d\n", __func__, CONNECT_PORT);
    if (NULL == pcoex_info) {
        RTW_INFO("coex_info: NULL\n");
        status =  _FAIL;
    }
    kernel_socket_err = sock_create(PF_INET, SOCK_DGRAM, 0, &pcoex_info->udpsock);
    if (kernel_socket_err < 0) {
        RTW_INFO("Error during creation of socket error:%d\n", kernel_socket_err);
        status = _FAIL;
    } else {
        _rtw_memset(&(pcoex_info->wifi_sockaddr), 0, sizeof(pcoex_info->wifi_sockaddr));
        pcoex_info->wifi_sockaddr.sin_family = AF_INET;
        pcoex_info->wifi_sockaddr.sin_port = htons(CONNECT_PORT);
        pcoex_info->wifi_sockaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
        _rtw_memset(&(pcoex_info->bt_sockaddr), 0, sizeof(pcoex_info->bt_sockaddr));
        pcoex_info->bt_sockaddr.sin_family = AF_INET;
        pcoex_info->bt_sockaddr.sin_port = htons(CONNECT_PORT_BT);
        pcoex_info->bt_sockaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
        pcoex_info->sk_store = NULL;
        kernel_socket_err = pcoex_info->udpsock->ops->bind(pcoex_info->udpsock, (struct sockaddr *)&pcoex_info->wifi_sockaddr,
                    sizeof(pcoex_info->wifi_sockaddr));
        if (kernel_socket_err == 0) {
            RTW_INFO("binding socket success\n");
            pcoex_info->udpsock->sk->sk_data_ready = rtw_btcoex_recvmsg_init;
            pcoex_info->sock_open |=  KERNEL_SOCKET_OK;
            pcoex_info->BT_attend = _FALSE;
            RTW_INFO("WIFI sending attend_req\n");
            rtw_btcoex_sendmsgbysocket(padapter, attend_req, sizeof(attend_req), _TRUE);
            status = _SUCCESS;
        } else {
            pcoex_info->BT_attend = _FALSE;
            sock_release(pcoex_info->udpsock); /* bind fail release socket */
            RTW_INFO("Error binding socket: %d\n", kernel_socket_err);
            status = _FAIL;
        }
    }
    return status;
}
void rtw_btcoex_close_kernel_socket(_adapter *padapter)
{
    struct bt_coex_info *pcoex_info = &padapter->coex_info;
    if (pcoex_info->sock_open & KERNEL_SOCKET_OK) {
        RTW_INFO("release kernel socket\n");
        sock_release(pcoex_info->udpsock);
        pcoex_info->sock_open &= ~(KERNEL_SOCKET_OK);
        if (_TRUE == pcoex_info->BT_attend)
            pcoex_info->BT_attend = _FALSE;
        RTW_INFO("sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
    }
}
void rtw_btcoex_init_socket(_adapter *padapter)
{
    u8 is_invite = _FALSE;
    struct bt_coex_info *pcoex_info = &padapter->coex_info;
    RTW_INFO("%s\n", __func__);
    if (_FALSE == pcoex_info->is_exist) {
        _rtw_memset(pcoex_info, 0, sizeof(struct bt_coex_info));
        pcoex_info->btcoex_wq = create_workqueue("BTCOEX");
        INIT_DELAYED_WORK(&pcoex_info->recvmsg_work,
                  (void *)rtw_btcoex_recvmsgbysocket);
        pbtcoexadapter = padapter;
        /* We expect BT is off if BT don't send ack to wifi */
        RTW_INFO("We expect BT is off if BT send ack to wifi\n");
        rtw_btcoex_pta_off_on_notify(pbtcoexadapter, _FALSE);
        if (rtw_btcoex_create_kernel_socket(padapter) == _SUCCESS)
            pcoex_info->is_exist = _TRUE;
        else {
            pcoex_info->is_exist = _FALSE;
            pbtcoexadapter = NULL;
        }
        RTW_INFO("%s: pbtcoexadapter:%p, coex_info->is_exist: %s\n"
            , __func__, pbtcoexadapter, pcoex_info->is_exist == _TRUE ? "TRUE" : "FALSE");
    }
}
void rtw_btcoex_close_socket(_adapter *padapter)
{
    struct bt_coex_info *pcoex_info = &padapter->coex_info;
    RTW_INFO("%s--coex_info->is_exist: %s, pcoex_info->BT_attend:%s\n"
        , __func__, pcoex_info->is_exist == _TRUE ? "TRUE" : "FALSE", pcoex_info->BT_attend == _TRUE ? "TRUE" : "FALSE");
    if (_TRUE == pcoex_info->is_exist) {
        if (_TRUE == pcoex_info->BT_attend) {
            /*inform BT wifi leave*/
            rtw_btcoex_sendmsgbysocket(padapter, wifi_leave, sizeof(wifi_leave), _FALSE);
            msleep(50);
        }
        if (pcoex_info->btcoex_wq != NULL) {
            flush_workqueue(pcoex_info->btcoex_wq);
            destroy_workqueue(pcoex_info->btcoex_wq);
        }
        rtw_btcoex_close_kernel_socket(padapter);
        pbtcoexadapter = NULL;
        pcoex_info->is_exist = _FALSE;
    }
}
void rtw_btcoex_dump_tx_msg(u8 *tx_msg, u8 len, u8 *msg_name)
{
    u8    i = 0;
    RTW_INFO("======> Msg name: %s\n", msg_name);
    for (i = 0; i < len; i++)
        printk("%02x ", tx_msg[i]);
    printk("\n");
    RTW_INFO("Msg name: %s <======\n", msg_name);
}
/* Porting from Windows team */
void rtw_btcoex_SendEventExtBtCoexControl(PADAPTER padapter, u8 bNeedDbgRsp, u8 dataLen, void *pData)
{
    u8            len = 0, tx_event_length = 0;
    u8             localBuf[32] = "";
    u8            *pRetPar;
    u8            opCode = 0;
    u8            *pInBuf = (pu1Byte)pData;
    u8            *pOpCodeContent;
    rtw_HCI_event *pEvent;
    opCode = pInBuf[0];
    RTW_INFO("%s, OPCode:%02x\n", __func__, opCode);
    pEvent = (rtw_HCI_event *)(&localBuf[0]);
    /* len += bthci_ExtensionEventHeaderRtk(&localBuf[0], */
    /*    HCI_EVENT_EXT_BT_COEX_CONTROL); */
    pEvent->EventCode = HCI_EVENT_EXTENSION_RTK;
    pEvent->Data[0] = HCI_EVENT_EXT_BT_COEX_CONTROL;    /* extension event code */
    len++;
    /* Return parameters starts from here */
    pRetPar = &pEvent->Data[len];
    _rtw_memcpy(&pRetPar[0], pData, dataLen);
    len += dataLen;
    pEvent->Length = len;
    /* total tx event length + EventCode length + sizeof(length) */
    tx_event_length = pEvent->Length + 2;
#if 0
    rtw_btcoex_dump_tx_msg((u8 *)pEvent, tx_event_length, "BT COEX CONTROL", _FALSE);
#endif
    rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
}
/* Porting from Windows team */
void rtw_btcoex_SendEventExtBtInfoControl(PADAPTER padapter, u8 dataLen, void *pData)
{
    rtw_HCI_event *pEvent;
    u8            *pRetPar;
    u8            len = 0, tx_event_length = 0;
    u8             localBuf[32] = "";
    struct bt_coex_info *pcoex_info = &padapter->coex_info;
    PBT_MGNT        pBtMgnt = &pcoex_info->BtMgnt;
    /* RTW_INFO("%s\n",__func__);*/
    if (pBtMgnt->ExtConfig.HCIExtensionVer < 4) { /* not support */
        RTW_INFO("ERROR: HCIExtensionVer = %d, HCIExtensionVer<4 !!!!\n", pBtMgnt->ExtConfig.HCIExtensionVer);
        return;
    }
    pEvent = (rtw_HCI_event *)(&localBuf[0]);
    /* len += bthci_ExtensionEventHeaderRtk(&localBuf[0], */
    /*        HCI_EVENT_EXT_BT_INFO_CONTROL); */
    pEvent->EventCode = HCI_EVENT_EXTENSION_RTK;
    pEvent->Data[0] = HCI_EVENT_EXT_BT_INFO_CONTROL;        /* extension event code */
    len++;
    /* Return parameters starts from here */
    pRetPar = &pEvent->Data[len];
    _rtw_memcpy(&pRetPar[0], pData, dataLen);
    len += dataLen;
    pEvent->Length = len;
    /* total tx event length + EventCode length + sizeof(length) */
    tx_event_length = pEvent->Length + 2;
#if 0
    rtw_btcoex_dump_tx_msg((u8 *)pEvent, tx_event_length, "BT INFO CONTROL");
#endif
    rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
}
void rtw_btcoex_SendScanNotify(PADAPTER padapter, u8 scanType)
{
    u8    len = 0, tx_event_length = 0;
    u8     localBuf[7] = "";
    u8    *pRetPar;
    u8    *pu1Temp;
    rtw_HCI_event *pEvent;
    struct bt_coex_info *pcoex_info = &padapter->coex_info;
    PBT_MGNT        pBtMgnt = &pcoex_info->BtMgnt;
    /*    if(!pBtMgnt->BtOperationOn)
     *        return; */
    pEvent = (rtw_HCI_event *)(&localBuf[0]);
    /*    len += bthci_ExtensionEventHeaderRtk(&localBuf[0],
     *            HCI_EVENT_EXT_WIFI_SCAN_NOTIFY); */
    pEvent->EventCode = HCI_EVENT_EXTENSION_RTK;
    pEvent->Data[0] = HCI_EVENT_EXT_WIFI_SCAN_NOTIFY;        /* extension event code */
    len++;
    /* Return parameters starts from here */
    /* pRetPar = &PPacketIrpEvent->Data[len]; */
    /* pu1Temp = (u8 *)&pRetPar[0]; */
    /* *pu1Temp = scanType; */
    pEvent->Data[len] = scanType;
    len += 1;
    pEvent->Length = len;
    /* total tx event length + EventCode length + sizeof(length) */
    tx_event_length = pEvent->Length + 2;
#if 0
    rtw_btcoex_dump_tx_msg((u8 *)pEvent, tx_event_length, "WIFI SCAN OPERATION");
#endif
    rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
}
#endif /* CONFIG_BT_COEXIST_SOCKET_TRX */
#endif /* CONFIG_BT_COEXIST */
Diff truncated after the above file
linux-bsp/drivers/rtl8188eus/core/rtw_btcoex_wifionly.c linux-bsp/drivers/rtl8188eus/core/rtw_cmd.c linux-bsp/drivers/rtl8188eus/core/rtw_debug.c linux-bsp/drivers/rtl8188eus/core/rtw_eeprom.c linux-bsp/drivers/rtl8188eus/core/rtw_ieee80211.c linux-bsp/drivers/rtl8188eus/core/rtw_io.c linux-bsp/drivers/rtl8188eus/core/rtw_ioctl_query.c linux-bsp/drivers/rtl8188eus/core/rtw_ioctl_rtl.c linux-bsp/drivers/rtl8188eus/core/rtw_ioctl_set.c linux-bsp/drivers/rtl8188eus/core/rtw_iol.c linux-bsp/drivers/rtl8188eus/core/rtw_mem.c linux-bsp/drivers/rtl8188eus/core/rtw_mi.c linux-bsp/drivers/rtl8188eus/core/rtw_mlme.c linux-bsp/drivers/rtl8188eus/core/rtw_mlme_ext.c linux-bsp/drivers/rtl8188eus/core/rtw_mp.c linux-bsp/drivers/rtl8188eus/core/rtw_mp_ioctl.c linux-bsp/drivers/rtl8188eus/core/rtw_odm.c linux-bsp/drivers/rtl8188eus/core/rtw_p2p.c linux-bsp/drivers/rtl8188eus/core/rtw_pwrctrl.c linux-bsp/drivers/rtl8188eus/core/rtw_recv.c linux-bsp/drivers/rtl8188eus/core/rtw_rf.c linux-bsp/drivers/rtl8188eus/core/rtw_sdio.c linux-bsp/drivers/rtl8188eus/core/rtw_security.c linux-bsp/drivers/rtl8188eus/core/rtw_sreset.c linux-bsp/drivers/rtl8188eus/core/rtw_sta_mgt.c linux-bsp/drivers/rtl8188eus/core/rtw_tdls.c linux-bsp/drivers/rtl8188eus/core/rtw_vht.c linux-bsp/drivers/rtl8188eus/core/rtw_wapi.c linux-bsp/drivers/rtl8188eus/core/rtw_wapi_sms4.c linux-bsp/drivers/rtl8188eus/core/rtw_wlan_util.c linux-bsp/drivers/rtl8188eus/core/rtw_xmit.c linux-bsp/drivers/rtl8188eus/hal/HalPwrSeqCmd.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8188c2Ant.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8192d2Ant.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8192e1Ant.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8192e2Ant.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723a1Ant.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723a2Ant.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723b1Ant.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8723b2Ant.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8812a1Ant.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8812a2Ant.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8821a1Ant.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtc8821a2Ant.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/HalBtcOutSrc.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC-BTCoexist/Mp_Precomp.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/HalPhyRf.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/HalPhyRf.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/PhyDM_Adaptivity.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/PhyDM_Adaptivity.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_AntDiv.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_AntDiv.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_HWConfig.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_HWConfig.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_RegDefine11AC.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_RegDefine11N.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_debug.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_debug.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_interface.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_interface.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_precomp.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_reg.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/odm_types.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/Hal8188ERateAdaptive.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/Hal8188ERateAdaptive.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/Hal8188EReg.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_BB.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_BB.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_FW.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_FW.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_MAC.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_MAC.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_RF.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalHWImg8188E_RF.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalPhyRf_8188e.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/HalPhyRf_8188e.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/odm_RTL8188E.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/odm_RTL8188E.h linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/odm_RegConfig8188E.c linux-bsp/drivers/rtl8188eus/hal/OUTSRC/rtl8188e/odm_RegConfig8188E.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8192e1ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8192e1ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8192e2ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8192e2ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8703b1ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8703b1ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723b1ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723b1ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723b2ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723b2ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723bwifionly.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723bwifionly.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723d1ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723d1ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723d2ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8723d2ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8812a1ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8812a1ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8812a2ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8812a2ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821a1ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821a1ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821a2ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821a2ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821c1ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821c1ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821c2ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821c2ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821cwifionly.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8821cwifionly.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8822b1ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8822b1ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8822b2ant.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8822b2ant.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8822bwifionly.c linux-bsp/drivers/rtl8188eus/hal/btc/halbtc8822bwifionly.h linux-bsp/drivers/rtl8188eus/hal/btc/halbtcoutsrc.h linux-bsp/drivers/rtl8188eus/hal/btc/mp_precomp.h linux-bsp/drivers/rtl8188eus/hal/efuse/efuse_mask.h linux-bsp/drivers/rtl8188eus/hal/efuse/rtl8188e/HalEfuseMask8188E_PCIE.c linux-bsp/drivers/rtl8188eus/hal/efuse/rtl8188e/HalEfuseMask8188E_PCIE.h linux-bsp/drivers/rtl8188eus/hal/efuse/rtl8188e/HalEfuseMask8188E_SDIO.c linux-bsp/drivers/rtl8188eus/hal/efuse/rtl8188e/HalEfuseMask8188E_SDIO.h linux-bsp/drivers/rtl8188eus/hal/efuse/rtl8188e/HalEfuseMask8188E_USB.c linux-bsp/drivers/rtl8188eus/hal/efuse/rtl8188e/HalEfuseMask8188E_USB.h linux-bsp/drivers/rtl8188eus/hal/hal_btcoex.c linux-bsp/drivers/rtl8188eus/hal/hal_btcoex_wifionly.c linux-bsp/drivers/rtl8188eus/hal/hal_com.c linux-bsp/drivers/rtl8188eus/hal/hal_com_c2h.h linux-bsp/drivers/rtl8188eus/hal/hal_com_phycfg.c linux-bsp/drivers/rtl8188eus/hal/hal_dm.c linux-bsp/drivers/rtl8188eus/hal/hal_dm.h linux-bsp/drivers/rtl8188eus/hal/hal_halmac.c linux-bsp/drivers/rtl8188eus/hal/hal_halmac.h linux-bsp/drivers/rtl8188eus/hal/hal_hci/hal_usb.c linux-bsp/drivers/rtl8188eus/hal/hal_intf.c linux-bsp/drivers/rtl8188eus/hal/hal_mcc.c linux-bsp/drivers/rtl8188eus/hal/hal_mp.c linux-bsp/drivers/rtl8188eus/hal/hal_phy.c linux-bsp/drivers/rtl8188eus/hal/led/hal_usb_led.c linux-bsp/drivers/rtl8188eus/hal/phydm/halhwimg.h linux-bsp/drivers/rtl8188eus/hal/phydm/halphyrf_ap.c linux-bsp/drivers/rtl8188eus/hal/phydm/halphyrf_ap.h linux-bsp/drivers/rtl8188eus/hal/phydm/halphyrf_ce.c linux-bsp/drivers/rtl8188eus/hal/phydm/halphyrf_ce.h linux-bsp/drivers/rtl8188eus/hal/phydm/halphyrf_win.c linux-bsp/drivers/rtl8188eus/hal/phydm/halphyrf_win.h linux-bsp/drivers/rtl8188eus/hal/phydm/mp_precomp.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_acs.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_acs.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_adaptivity.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_adaptivity.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_adc_sampling.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_adc_sampling.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_antdect.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_antdect.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_antdiv.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_antdiv.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_beamforming.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_beamforming.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_ccx.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_ccx.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_cfotracking.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_cfotracking.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_debug.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_debug.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dfs.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dfs.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dig.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dig.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dynamic_rx_path.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dynamic_rx_path.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dynamicbbpowersaving.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dynamicbbpowersaving.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dynamictxpower.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_dynamictxpower.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_edcaturbocheck.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_edcaturbocheck.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_features.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_hwconfig.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_hwconfig.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_interface.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_interface.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_iqk.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_kfree.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_kfree.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_noisemonitor.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_noisemonitor.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_pathdiv.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_pathdiv.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_powertracking_ap.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_powertracking_ap.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_powertracking_ce.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_powertracking_ce.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_powertracking_win.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_powertracking_win.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_pre_define.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_precomp.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_rainfo.c linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_rainfo.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_reg.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_regdefine11ac.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_regdefine11n.h linux-bsp/drivers/rtl8188eus/hal/phydm/phydm_types.h linux-bsp/drivers/rtl8188eus/hal/phydm/rtchnlplan.c linux-bsp/drivers/rtl8188eus/hal/phydm/rtchnlplan.h linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/hal8188erateadaptive.c linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/hal8188erateadaptive.h linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/hal8188ereg.h linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_bb.c linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_bb.h linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_mac.c linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_mac.h linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_rf.c linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_rf.h linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_s_fw.c linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_s_fw.h linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_t_fw.c linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halhwimg8188e_t_fw.h linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halphyrf_8188e_ap.c linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halphyrf_8188e_ap.h linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halphyrf_8188e_ce.c linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halphyrf_8188e_ce.h linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halphyrf_8188e_win.c linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/halphyrf_8188e_win.h linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/phydm_regconfig8188e.c linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/phydm_regconfig8188e.h linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/phydm_rtl8188e.c linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/phydm_rtl8188e.h linux-bsp/drivers/rtl8188eus/hal/phydm/rtl8188e/version_rtl8188e.h linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/halcomtxbf.c linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/halcomtxbf.h linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbf8192e.c linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbf8192e.h linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbf8814a.c linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbf8814a.h linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbf8822b.c linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbf8822b.h linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbfinterface.c linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbfinterface.h linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbfjaguar.c linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/haltxbfjaguar.h linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/phydm_hal_txbf_api.c linux-bsp/drivers/rtl8188eus/hal/phydm/txbf/phydm_hal_txbf_api.h linux-bsp/drivers/rtl8188eus/hal/rtl8188e/Hal8188EPwrSeq.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/hal8188e_s_fw.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/hal8188e_s_fw.h linux-bsp/drivers/rtl8188eus/hal/rtl8188e/hal8188e_t_fw.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/hal8188e_t_fw.h linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_cmd.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_dm.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_hal_init.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_mp.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_phycfg.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_rf6052.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_rxdesc.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_sreset.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/rtl8188e_xmit.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/usb/rtl8188eu_led.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/usb/rtl8188eu_recv.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/usb/rtl8188eu_xmit.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/usb/usb_halinit.c linux-bsp/drivers/rtl8188eus/hal/rtl8188e/usb/usb_ops_linux.c linux-bsp/drivers/rtl8188eus/include/Hal8188EPhyCfg.h linux-bsp/drivers/rtl8188eus/include/Hal8188EPhyReg.h linux-bsp/drivers/rtl8188eus/include/Hal8188EPwrSeq.h linux-bsp/drivers/rtl8188eus/include/Hal8188FPhyCfg.h linux-bsp/drivers/rtl8188eus/include/Hal8188FPhyReg.h linux-bsp/drivers/rtl8188eus/include/Hal8188FPwrSeq.h linux-bsp/drivers/rtl8188eus/include/Hal8192CPhyCfg.h linux-bsp/drivers/rtl8188eus/include/Hal8192CPhyReg.h linux-bsp/drivers/rtl8188eus/include/Hal8192DPhyCfg.h linux-bsp/drivers/rtl8188eus/include/Hal8192DPhyReg.h linux-bsp/drivers/rtl8188eus/include/Hal8192EPhyCfg.h linux-bsp/drivers/rtl8188eus/include/Hal8192EPhyReg.h linux-bsp/drivers/rtl8188eus/include/Hal8192EPwrSeq.h linux-bsp/drivers/rtl8188eus/include/Hal8703BPhyCfg.h linux-bsp/drivers/rtl8188eus/include/Hal8703BPhyReg.h linux-bsp/drivers/rtl8188eus/include/Hal8703BPwrSeq.h linux-bsp/drivers/rtl8188eus/include/Hal8723APhyCfg.h linux-bsp/drivers/rtl8188eus/include/Hal8723APhyReg.h linux-bsp/drivers/rtl8188eus/include/Hal8723BPhyCfg.h linux-bsp/drivers/rtl8188eus/include/Hal8723BPhyReg.h linux-bsp/drivers/rtl8188eus/include/Hal8723BPwrSeq.h linux-bsp/drivers/rtl8188eus/include/Hal8723DPhyCfg.h linux-bsp/drivers/rtl8188eus/include/Hal8723DPhyReg.h linux-bsp/drivers/rtl8188eus/include/Hal8723DPwrSeq.h linux-bsp/drivers/rtl8188eus/include/Hal8723PwrSeq.h linux-bsp/drivers/rtl8188eus/include/Hal8812PhyCfg.h linux-bsp/drivers/rtl8188eus/include/Hal8812PhyReg.h linux-bsp/drivers/rtl8188eus/include/Hal8812PwrSeq.h linux-bsp/drivers/rtl8188eus/include/Hal8814PhyCfg.h linux-bsp/drivers/rtl8188eus/include/Hal8814PhyReg.h linux-bsp/drivers/rtl8188eus/include/Hal8814PwrSeq.h linux-bsp/drivers/rtl8188eus/include/Hal8821APwrSeq.h linux-bsp/drivers/rtl8188eus/include/HalPwrSeqCmd.h linux-bsp/drivers/rtl8188eus/include/HalVerDef.h linux-bsp/drivers/rtl8188eus/include/autoconf.h linux-bsp/drivers/rtl8188eus/include/basic_types.h linux-bsp/drivers/rtl8188eus/include/byteorder/big_endian.h linux-bsp/drivers/rtl8188eus/include/byteorder/generic.h linux-bsp/drivers/rtl8188eus/include/byteorder/little_endian.h linux-bsp/drivers/rtl8188eus/include/byteorder/swab.h linux-bsp/drivers/rtl8188eus/include/byteorder/swabb.h linux-bsp/drivers/rtl8188eus/include/circ_buf.h linux-bsp/drivers/rtl8188eus/include/cmd_osdep.h linux-bsp/drivers/rtl8188eus/include/custom_gpio.h linux-bsp/drivers/rtl8188eus/include/drv_conf.h linux-bsp/drivers/rtl8188eus/include/drv_types.h linux-bsp/drivers/rtl8188eus/include/drv_types_ce.h linux-bsp/drivers/rtl8188eus/include/drv_types_gspi.h linux-bsp/drivers/rtl8188eus/include/drv_types_linux.h linux-bsp/drivers/rtl8188eus/include/drv_types_pci.h linux-bsp/drivers/rtl8188eus/include/drv_types_sdio.h linux-bsp/drivers/rtl8188eus/include/drv_types_xp.h linux-bsp/drivers/rtl8188eus/include/ethernet.h linux-bsp/drivers/rtl8188eus/include/gspi_hal.h linux-bsp/drivers/rtl8188eus/include/gspi_ops.h linux-bsp/drivers/rtl8188eus/include/gspi_ops_linux.h linux-bsp/drivers/rtl8188eus/include/gspi_osintf.h linux-bsp/drivers/rtl8188eus/include/h2clbk.h linux-bsp/drivers/rtl8188eus/include/hal_btcoex.h linux-bsp/drivers/rtl8188eus/include/hal_btcoex_wifionly.h linux-bsp/drivers/rtl8188eus/include/hal_com.h linux-bsp/drivers/rtl8188eus/include/hal_com_h2c.h linux-bsp/drivers/rtl8188eus/include/hal_com_led.h linux-bsp/drivers/rtl8188eus/include/hal_com_phycfg.h linux-bsp/drivers/rtl8188eus/include/hal_com_reg.h linux-bsp/drivers/rtl8188eus/include/hal_data.h linux-bsp/drivers/rtl8188eus/include/hal_gspi.h linux-bsp/drivers/rtl8188eus/include/hal_ic_cfg.h linux-bsp/drivers/rtl8188eus/include/hal_intf.h linux-bsp/drivers/rtl8188eus/include/hal_pg.h linux-bsp/drivers/rtl8188eus/include/hal_phy.h linux-bsp/drivers/rtl8188eus/include/hal_phy_reg.h linux-bsp/drivers/rtl8188eus/include/hal_sdio.h linux-bsp/drivers/rtl8188eus/include/ieee80211.h linux-bsp/drivers/rtl8188eus/include/ieee80211_ext.h linux-bsp/drivers/rtl8188eus/include/if_ether.h linux-bsp/drivers/rtl8188eus/include/ioctl_cfg80211.h linux-bsp/drivers/rtl8188eus/include/ip.h linux-bsp/drivers/rtl8188eus/include/linux/wireless.h linux-bsp/drivers/rtl8188eus/include/mlme_osdep.h linux-bsp/drivers/rtl8188eus/include/mp_custom_oid.h linux-bsp/drivers/rtl8188eus/include/nic_spec.h linux-bsp/drivers/rtl8188eus/include/osdep_intf.h linux-bsp/drivers/rtl8188eus/include/osdep_service.h linux-bsp/drivers/rtl8188eus/include/osdep_service_bsd.h linux-bsp/drivers/rtl8188eus/include/osdep_service_ce.h linux-bsp/drivers/rtl8188eus/include/osdep_service_linux.h linux-bsp/drivers/rtl8188eus/include/osdep_service_xp.h linux-bsp/drivers/rtl8188eus/include/pci_hal.h linux-bsp/drivers/rtl8188eus/include/pci_ops.h linux-bsp/drivers/rtl8188eus/include/pci_osintf.h linux-bsp/drivers/rtl8188eus/include/recv_osdep.h linux-bsp/drivers/rtl8188eus/include/rtl8188e_cmd.h linux-bsp/drivers/rtl8188eus/include/rtl8188e_dm.h linux-bsp/drivers/rtl8188eus/include/rtl8188e_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8188e_led.h linux-bsp/drivers/rtl8188eus/include/rtl8188e_recv.h linux-bsp/drivers/rtl8188eus/include/rtl8188e_rf.h linux-bsp/drivers/rtl8188eus/include/rtl8188e_spec.h linux-bsp/drivers/rtl8188eus/include/rtl8188e_sreset.h linux-bsp/drivers/rtl8188eus/include/rtl8188e_xmit.h linux-bsp/drivers/rtl8188eus/include/rtl8188f_cmd.h linux-bsp/drivers/rtl8188eus/include/rtl8188f_dm.h linux-bsp/drivers/rtl8188eus/include/rtl8188f_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8188f_led.h linux-bsp/drivers/rtl8188eus/include/rtl8188f_recv.h linux-bsp/drivers/rtl8188eus/include/rtl8188f_rf.h linux-bsp/drivers/rtl8188eus/include/rtl8188f_spec.h linux-bsp/drivers/rtl8188eus/include/rtl8188f_sreset.h linux-bsp/drivers/rtl8188eus/include/rtl8188f_xmit.h linux-bsp/drivers/rtl8188eus/include/rtl8192c_cmd.h linux-bsp/drivers/rtl8188eus/include/rtl8192c_dm.h linux-bsp/drivers/rtl8188eus/include/rtl8192c_event.h linux-bsp/drivers/rtl8188eus/include/rtl8192c_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8192c_led.h linux-bsp/drivers/rtl8188eus/include/rtl8192c_recv.h linux-bsp/drivers/rtl8188eus/include/rtl8192c_rf.h linux-bsp/drivers/rtl8188eus/include/rtl8192c_spec.h linux-bsp/drivers/rtl8188eus/include/rtl8192c_sreset.h linux-bsp/drivers/rtl8188eus/include/rtl8192c_xmit.h linux-bsp/drivers/rtl8188eus/include/rtl8192d_cmd.h linux-bsp/drivers/rtl8188eus/include/rtl8192d_dm.h linux-bsp/drivers/rtl8188eus/include/rtl8192d_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8192d_led.h linux-bsp/drivers/rtl8188eus/include/rtl8192d_recv.h linux-bsp/drivers/rtl8188eus/include/rtl8192d_rf.h linux-bsp/drivers/rtl8188eus/include/rtl8192d_spec.h linux-bsp/drivers/rtl8188eus/include/rtl8192d_xmit.h linux-bsp/drivers/rtl8188eus/include/rtl8192e_cmd.h linux-bsp/drivers/rtl8188eus/include/rtl8192e_dm.h linux-bsp/drivers/rtl8188eus/include/rtl8192e_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8192e_led.h linux-bsp/drivers/rtl8188eus/include/rtl8192e_recv.h linux-bsp/drivers/rtl8188eus/include/rtl8192e_rf.h linux-bsp/drivers/rtl8188eus/include/rtl8192e_spec.h linux-bsp/drivers/rtl8188eus/include/rtl8192e_sreset.h linux-bsp/drivers/rtl8188eus/include/rtl8192e_xmit.h linux-bsp/drivers/rtl8188eus/include/rtl8703b_cmd.h linux-bsp/drivers/rtl8188eus/include/rtl8703b_dm.h linux-bsp/drivers/rtl8188eus/include/rtl8703b_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8703b_led.h linux-bsp/drivers/rtl8188eus/include/rtl8703b_recv.h linux-bsp/drivers/rtl8188eus/include/rtl8703b_rf.h linux-bsp/drivers/rtl8188eus/include/rtl8703b_spec.h linux-bsp/drivers/rtl8188eus/include/rtl8703b_sreset.h linux-bsp/drivers/rtl8188eus/include/rtl8703b_xmit.h linux-bsp/drivers/rtl8188eus/include/rtl8723a_cmd.h linux-bsp/drivers/rtl8188eus/include/rtl8723a_dm.h linux-bsp/drivers/rtl8188eus/include/rtl8723a_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8723a_led.h linux-bsp/drivers/rtl8188eus/include/rtl8723a_pg.h linux-bsp/drivers/rtl8188eus/include/rtl8723a_recv.h linux-bsp/drivers/rtl8188eus/include/rtl8723a_rf.h linux-bsp/drivers/rtl8188eus/include/rtl8723a_spec.h linux-bsp/drivers/rtl8188eus/include/rtl8723a_sreset.h linux-bsp/drivers/rtl8188eus/include/rtl8723a_xmit.h linux-bsp/drivers/rtl8188eus/include/rtl8723b_cmd.h linux-bsp/drivers/rtl8188eus/include/rtl8723b_dm.h linux-bsp/drivers/rtl8188eus/include/rtl8723b_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8723b_led.h linux-bsp/drivers/rtl8188eus/include/rtl8723b_recv.h linux-bsp/drivers/rtl8188eus/include/rtl8723b_rf.h linux-bsp/drivers/rtl8188eus/include/rtl8723b_spec.h linux-bsp/drivers/rtl8188eus/include/rtl8723b_sreset.h linux-bsp/drivers/rtl8188eus/include/rtl8723b_xmit.h linux-bsp/drivers/rtl8188eus/include/rtl8723d_cmd.h linux-bsp/drivers/rtl8188eus/include/rtl8723d_dm.h linux-bsp/drivers/rtl8188eus/include/rtl8723d_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8723d_led.h linux-bsp/drivers/rtl8188eus/include/rtl8723d_lps_poff.h linux-bsp/drivers/rtl8188eus/include/rtl8723d_recv.h linux-bsp/drivers/rtl8188eus/include/rtl8723d_rf.h linux-bsp/drivers/rtl8188eus/include/rtl8723d_spec.h linux-bsp/drivers/rtl8188eus/include/rtl8723d_sreset.h linux-bsp/drivers/rtl8188eus/include/rtl8723d_xmit.h linux-bsp/drivers/rtl8188eus/include/rtl8812a_cmd.h linux-bsp/drivers/rtl8188eus/include/rtl8812a_dm.h linux-bsp/drivers/rtl8188eus/include/rtl8812a_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8812a_led.h linux-bsp/drivers/rtl8188eus/include/rtl8812a_recv.h linux-bsp/drivers/rtl8188eus/include/rtl8812a_rf.h linux-bsp/drivers/rtl8188eus/include/rtl8812a_spec.h linux-bsp/drivers/rtl8188eus/include/rtl8812a_sreset.h linux-bsp/drivers/rtl8188eus/include/rtl8812a_xmit.h linux-bsp/drivers/rtl8188eus/include/rtl8814a_cmd.h linux-bsp/drivers/rtl8188eus/include/rtl8814a_dm.h linux-bsp/drivers/rtl8188eus/include/rtl8814a_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8814a_led.h linux-bsp/drivers/rtl8188eus/include/rtl8814a_recv.h linux-bsp/drivers/rtl8188eus/include/rtl8814a_rf.h linux-bsp/drivers/rtl8188eus/include/rtl8814a_spec.h linux-bsp/drivers/rtl8188eus/include/rtl8814a_sreset.h linux-bsp/drivers/rtl8188eus/include/rtl8814a_xmit.h linux-bsp/drivers/rtl8188eus/include/rtl8821a_spec.h linux-bsp/drivers/rtl8188eus/include/rtl8821a_xmit.h linux-bsp/drivers/rtl8188eus/include/rtl8821c_dm.h linux-bsp/drivers/rtl8188eus/include/rtl8821c_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8821c_spec.h linux-bsp/drivers/rtl8188eus/include/rtl8821ce_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8821cs_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8821cu_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8822b_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8822be_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8822bs_hal.h linux-bsp/drivers/rtl8188eus/include/rtl8822bu_hal.h linux-bsp/drivers/rtl8188eus/include/rtw_android.h linux-bsp/drivers/rtl8188eus/include/rtw_ap.h linux-bsp/drivers/rtl8188eus/include/rtw_beamforming.h linux-bsp/drivers/rtl8188eus/include/rtw_br_ext.h linux-bsp/drivers/rtl8188eus/include/rtw_bt_mp.h linux-bsp/drivers/rtl8188eus/include/rtw_btcoex.h linux-bsp/drivers/rtl8188eus/include/rtw_btcoex_wifionly.h linux-bsp/drivers/rtl8188eus/include/rtw_byteorder.h linux-bsp/drivers/rtl8188eus/include/rtw_cmd.h linux-bsp/drivers/rtl8188eus/include/rtw_debug.h linux-bsp/drivers/rtl8188eus/include/rtw_eeprom.h linux-bsp/drivers/rtl8188eus/include/rtw_efuse.h linux-bsp/drivers/rtl8188eus/include/rtw_event.h linux-bsp/drivers/rtl8188eus/include/rtw_ht.h linux-bsp/drivers/rtl8188eus/include/rtw_io.h linux-bsp/drivers/rtl8188eus/include/rtw_ioctl.h linux-bsp/drivers/rtl8188eus/include/rtw_ioctl_query.h linux-bsp/drivers/rtl8188eus/include/rtw_ioctl_rtl.h linux-bsp/drivers/rtl8188eus/include/rtw_ioctl_set.h linux-bsp/drivers/rtl8188eus/include/rtw_iol.h linux-bsp/drivers/rtl8188eus/include/rtw_mcc.h linux-bsp/drivers/rtl8188eus/include/rtw_mem.h linux-bsp/drivers/rtl8188eus/include/rtw_mi.h linux-bsp/drivers/rtl8188eus/include/rtw_mlme.h linux-bsp/drivers/rtl8188eus/include/rtw_mlme_ext.h linux-bsp/drivers/rtl8188eus/include/rtw_mp.h linux-bsp/drivers/rtl8188eus/include/rtw_mp_ioctl.h linux-bsp/drivers/rtl8188eus/include/rtw_mp_phy_regdef.h linux-bsp/drivers/rtl8188eus/include/rtw_odm.h linux-bsp/drivers/rtl8188eus/include/rtw_p2p.h linux-bsp/drivers/rtl8188eus/include/rtw_pwrctrl.h linux-bsp/drivers/rtl8188eus/include/rtw_qos.h linux-bsp/drivers/rtl8188eus/include/rtw_recv.h linux-bsp/drivers/rtl8188eus/include/rtw_rf.h linux-bsp/drivers/rtl8188eus/include/rtw_sdio.h linux-bsp/drivers/rtl8188eus/include/rtw_security.h linux-bsp/drivers/rtl8188eus/include/rtw_sreset.h linux-bsp/drivers/rtl8188eus/include/rtw_tdls.h linux-bsp/drivers/rtl8188eus/include/rtw_version.h linux-bsp/drivers/rtl8188eus/include/rtw_vht.h linux-bsp/drivers/rtl8188eus/include/rtw_wapi.h linux-bsp/drivers/rtl8188eus/include/rtw_wifi_regd.h linux-bsp/drivers/rtl8188eus/include/rtw_xmit.h linux-bsp/drivers/rtl8188eus/include/sdio_hal.h linux-bsp/drivers/rtl8188eus/include/sdio_ops.h linux-bsp/drivers/rtl8188eus/include/sdio_ops_ce.h linux-bsp/drivers/rtl8188eus/include/sdio_ops_linux.h linux-bsp/drivers/rtl8188eus/include/sdio_ops_xp.h linux-bsp/drivers/rtl8188eus/include/sdio_osintf.h linux-bsp/drivers/rtl8188eus/include/sta_info.h linux-bsp/drivers/rtl8188eus/include/usb_hal.h linux-bsp/drivers/rtl8188eus/include/usb_ops.h linux-bsp/drivers/rtl8188eus/include/usb_ops_linux.h linux-bsp/drivers/rtl8188eus/include/usb_osintf.h linux-bsp/drivers/rtl8188eus/include/usb_vendor_req.h linux-bsp/drivers/rtl8188eus/include/wifi.h linux-bsp/drivers/rtl8188eus/include/wlan_bssdef.h linux-bsp/drivers/rtl8188eus/include/xmit_osdep.h linux-bsp/drivers/rtl8188eus/os_dep/linux/custom_gpio_linux.c linux-bsp/drivers/rtl8188eus/os_dep/linux/ioctl_cfg80211.c linux-bsp/drivers/rtl8188eus/os_dep/linux/ioctl_cfg80211.h linux-bsp/drivers/rtl8188eus/os_dep/linux/ioctl_linux.c linux-bsp/drivers/rtl8188eus/os_dep/linux/ioctl_mp.c linux-bsp/drivers/rtl8188eus/os_dep/linux/mlme_linux.c linux-bsp/drivers/rtl8188eus/os_dep/linux/os_intfs.c linux-bsp/drivers/rtl8188eus/os_dep/linux/recv_linux.c linux-bsp/drivers/rtl8188eus/os_dep/linux/rtw_android.c linux-bsp/drivers/rtl8188eus/os_dep/linux/rtw_cfgvendor.c linux-bsp/drivers/rtl8188eus/os_dep/linux/rtw_cfgvendor.h linux-bsp/drivers/rtl8188eus/os_dep/linux/rtw_proc.c linux-bsp/drivers/rtl8188eus/os_dep/linux/rtw_proc.h linux-bsp/drivers/rtl8188eus/os_dep/linux/usb_intf.c linux-bsp/drivers/rtl8188eus/os_dep/linux/usb_ops_linux.c linux-bsp/drivers/rtl8188eus/os_dep/linux/wifi_regd.c linux-bsp/drivers/rtl8188eus/os_dep/linux/xmit_linux.c linux-bsp/drivers/rtl8188eus/os_dep/osdep_service.c linux-bsp/drivers/rtl8188eus/platform/custom_country_chplan.h linux-bsp/drivers/rtl8188eus/platform/platform_ARM_SUN50IW1P1_sdio.c linux-bsp/drivers/rtl8188eus/platform/platform_ARM_SUNnI_sdio.c linux-bsp/drivers/rtl8188eus/platform/platform_ARM_SUNxI_sdio.c linux-bsp/drivers/rtl8188eus/platform/platform_ARM_SUNxI_usb.c linux-bsp/drivers/rtl8188eus/platform/platform_ARM_WMT_sdio.c linux-bsp/drivers/rtl8188eus/platform/platform_RTK_DMP_usb.c linux-bsp/drivers/rtl8188eus/platform/platform_arm_act_sdio.c linux-bsp/drivers/rtl8188eus/platform/platform_ops.c linux-bsp/drivers/rtl8188eus/platform/platform_ops.h linux-bsp/drivers/rtl8188eus/platform/platform_sprd_sdio.c